+ --- Project | Makefile + --- src + --- api | ApiClass.cpp | ApiClass.h | ApiFunction.cpp | ApiFunction.h | \ --- user main.cpp
#include "ApiFunction.h" #include <cstring> int apiFunction(int v1, int v2){ return v1*v2; } void apiFunctionMutablePointer(double * value){ * value = *value * 100; } Data apiFunctionGetData(){ Data dt; dt.intValue = 1; dt.doubleValue = 3.1415; dt.ucharValue = 0xff; return dt; } Data GLOBAL_DATA; Data * apiFunctionGetPointerData(){ GLOBAL_DATA.intValue = 1*2; GLOBAL_DATA.doubleValue = 3.1415*2; GLOBAL_DATA.ucharValue = 0xAA; return &GLOBAL_DATA; } void apiFunctionMutablePointerData(Data * data){ data->intValue = data->intValue * 3; data->doubleValue = data->doubleValue *3; data->ucharValue = data->ucharValue * 3; } BigData apiFunctionGetBigData(){ BigData bd; bd.iv = 1; bd.v1 = 2; bd.v2 = 3; bd.v3 = 4; bd.v4 = 5; std::memset(bd.st,0,12); std::memmove(bd.st,"hello world",12); return bd; }
#ifndef SRC_API_APIFUNCTION_H_ #define SRC_API_APIFUNCTION_H_ #ifdef __cplusplus extern "C" { #endif int apiFunction(int v1, int v2); void apiFunctionMutablePointer(double * value); struct Data{ int intValue; double doubleValue; unsigned char ucharValue; }; struct BigData{ int iv; int v1:4; int v2:4; int v3:8; int v4:16; char st[12]; }; Data apiFunctionGetData(); Data * apiFunctionGetPointerData(); void apiFunctionMutablePointerData(Data * data); BigData apiFunctionGetBigData(); #ifdef __cplusplus } #endif #endif
#include "ApiClass.h" #include <iostream> ApiClass::ApiClass():value(0) { std::cout<<std::endl<<"create ApiClass value = "<<value<<std::endl; } ApiClass::ApiClass(int startValue): value(startValue){ std::cout<<std::endl<<"create ApiClass value = "<<value<<std::endl; } ApiClass::~ApiClass() { std::cout<<std::endl<<"delete ApiClass"<<std::endl; } int ApiClass::method(int vl){ value +=vl; return value; }
#ifndef SRC_API_APICLASS_H_ #define SRC_API_APICLASS_H_ class ApiClass { public: ApiClass(); ApiClass(int startValue); virtual ~ApiClass(); int method(int vl); private: int value; }; #endif
#include <iostream> #include "ApiFunction.h" #include "ApiClass.h" int main(){ std::cout<<"start work"<<std::endl; std::cout<<"=============================================="<<std::endl; std::cout<<"call apiFunction(10,20) = "<<apiFunction(10,20)<<std::endl; std::cout<<"call apiFunction(30,40) = "<<apiFunction(30,40)<<std::endl; std::cout<<"=============================================="<<std::endl; ApiClass ac01; std::cout<<"call ac01.method(30) = "<<ac01.method(30)<<std::endl; std::cout<<"call ac01.method(40) = "<<ac01.method(40)<<std::endl; std::cout<<"=============================================="<<std::endl; ApiClass ac02(10); std::cout<<"call ac02.method(30) = "<<ac02.method(30)<<std::endl; std::cout<<"call ac02.method(40) = "<<ac02.method(40)<<std::endl; }
FOLDER_EXECUTABLE = bin/ EXECUTABLE_NAME = Project.exe EXECUTABLE = $(FOLDER_EXECUTABLE)$(EXECUTABLE_NAME) FOLDERS = bin bin/src bin/src/api bin/src/user SOURSES = src/user/main.cpp src/api/ApiClass.cpp src/api/ApiFunction.cpp CC = g++ CFLAGS = -c -Wall -Isrc/helper -Isrc/api LDFLAGS = OBJECTS = $(SOURSES:.cpp=.o) OBJECTS_PATH = $(addprefix $(FOLDER_EXECUTABLE),$(OBJECTS)) all: $(SOURSES) $(EXECUTABLE) $(EXECUTABLE): $(OBJECTS) $(CC) $(LDLAGS) $(OBJECTS_PATH) -o $@ .cpp.o: mkdir -p $(FOLDERS) $(CC) $(CFLAGS) $< -o $(FOLDER_EXECUTABLE)$@ clean: rm -rf $(OBJECTS) $(EXECUTABLE)
import subprocess class CallCommandHelperException(Exception): pass def CallCommandHelper(cmd): with subprocess.Popen(cmd, stdout=subprocess.PIPE,shell=True) as proc: if proc.wait() != 0: raise CallCommandHelperException("error :" +cmd)
import os from helpers import callCommandHelper def CreateDll(folderTargetName, fileTargetName,fileSO): templateCompill = "g++ {flags} {fileSourse} -o {fileTarget}" templateLinc = "g++ -shared {objectfile} -o {fileTarget}" if os.path.exists(folderTargetName) == False: os.makedirs(folderTargetName) #---------------delete old version----------------------------------- if os.path.exists(fileTargetName): os.remove(fileTargetName) for fso in fileSO: if os.path.exists(fso["rezultName"]): os.remove(fso["rezultName"]) #---------------compil ----------------------------------------------- for filePair in fileSO: fileSourseName = filePair["sourseName"] fileObjecteName = filePair["rezultName"] flagCompil = filePair["flagsCompil"] cmd = templateCompill.format( fileSourse = fileSourseName, flags = flagCompil, fileTarget = fileObjecteName) callCommandHelper.CallCommandHelper(cmd) #---------------linck----------------------------------------------- fileObjectName = " " for filePair in fileSO: fileObjectName = fileObjectName + filePair["rezultName"]+" " cmd = templateLinc.format( objectfile = fileObjectName, fileTarget = fileTargetName) callCommandHelper.CallCommandHelper(cmd) #======================================================
import os import ctypes from helpers import creteDll import unittest class Data(ctypes.Structure): _fields_ = [("intValue",ctypes.c_int),("doubleValue",ctypes.c_double),("ucharValue",ctypes.c_ubyte)] class BigData(ctypes.Structure): _fields_ = [("iv",ctypes.c_int), ("v1",ctypes.c_int,4), ("v2",ctypes.c_int,4), ("v3",ctypes.c_int,8), ("v4",ctypes.c_int,16), ("st",ctypes.c_char*12)] class ApiFunctionTest(unittest.TestCase): @classmethod def setUpClass(self): folderTargetName = os.path.join(os.path.dirname(__file__),"ApiFunctionTest") fileSO = [ {"sourseName":"../src/api/ApiFunction.cpp", "flagsCompil":"-Wall -c -fPIC", "rezultName" :os.path.join(folderTargetName,"ApiFunction.o")} ] fileTargetName = os.path.join(folderTargetName,"ApiFunction.dll") #============================================================= creteDll.CreateDll(folderTargetName, fileTargetName, fileSO) lib = ctypes.cdll.LoadLibrary(fileTargetName) self.apiFunction = lib.apiFunction self.apiFunction.restype = ctypes.c_int self.apiFunctionMutablePointer = lib.apiFunctionMutablePointer self.apiFunctionMutablePointer.argtype = ctypes.POINTER(ctypes.c_double) self.apiFunctionGetData = lib.apiFunctionGetData self.apiFunctionGetData.restype = Data self.apiFunctionGetPointerData = lib.apiFunctionGetPointerData self.apiFunctionGetPointerData.restype = ctypes.POINTER(Data) self.apiFunctionMutablePointerData = lib.apiFunctionMutablePointerData self.apiFunctionMutablePointerData.argtype = ctypes.POINTER(Data) self.apiFunctionGetBigData = lib.apiFunctionGetBigData self.apiFunctionGetBigData.restype = BigData def test_var1(self): self.assertEqual(self.apiFunction(10,20), 200,'10*20 = 200') def test_var2(self): self.assertEqual(self.apiFunction(30,40), 1200,'30*40 = 1200') def test_var3(self): vl = ctypes.c_double(1.1) self.apiFunctionMutablePointer(ctypes.pointer(vl) ) self.assertEqual(vl.value, 110.00000000000001,'vl != 110') def test_var4(self): data = self.apiFunctionGetData() self.assertEqual(data.intValue, 1,'data.intValue != 1') self.assertEqual(data.doubleValue, 3.1415,'data.doubleValue != 3.1415') self.assertEqual(data.ucharValue, 0xff,'data.ucharValue != 0xff') def test_var5(self): pointerData = self.apiFunctionGetPointerData() self.assertEqual(pointerData.contents.intValue, 1*2,'data.intValue != 1*2') self.assertEqual(pointerData.contents.doubleValue, 3.1415*2,'data.doubleValue != 3.1415 * 2') self.assertEqual(pointerData.contents.ucharValue, 0xAA,'data.ucharValue != 0xAA') def test_var5(self): pointerData = ctypes.pointer(Data()) pointerData.contents.intValue = ctypes.c_int(10) pointerData.contents.doubleValue = ctypes.c_double(20) pointerData.contents.ucharValue = ctypes.c_ubyte(85) self.apiFunctionMutablePointerData(pointerData) self.assertEqual(pointerData.contents.intValue, 30,'data.intValue != 30') self.assertEqual(pointerData.contents.doubleValue, 60,'data.doubleValue != 60') self.assertEqual(pointerData.contents.ucharValue, 0xff,'data.ucharValue != 0xff') def test_var6(self): bigData = self.apiFunctionGetBigData() st = ctypes.c_char_p(bigData.st).value self.assertEqual(bigData.iv, 1,'1') self.assertEqual(bigData.v1, 2,'2') self.assertEqual(bigData.v2, 3,'3') self.assertEqual(bigData.v3, 4,'4') self.assertEqual(bigData.v4, 5,'5') self.assertEqual(st in b"hello world",True,'getting string')
#include "ApiClass.h" #ifdef __cplusplus extern "C" { #endif ApiClass * pEmptyApiClass = 0; ApiClass * pApiClass = 0; void createEmptyApiClass(){ if(pEmptyApiClass != 0){ delete pEmptyApiClass; } pEmptyApiClass = new ApiClass; } void deleteEmptyApiClass(){ if(pEmptyApiClass != 0){ delete pEmptyApiClass; pEmptyApiClass=0; } } void createApiClass(int value){ if(pApiClass != 0){ delete pApiClass; } pApiClass = new ApiClass(value); } void deleteApiClass(){ if(pApiClass != 0){ delete pApiClass; pApiClass=0; } } int callEmptyApiClassMethod(int vl){ return pEmptyApiClass->method(vl); } int callApiClassMethod(int vl){ return pApiClass->method(vl); } #ifdef __cplusplus } #endif
import os import ctypes from helpers import creteDll import unittest class ApiClassTest(unittest.TestCase): @classmethod def setUpClass(self): folderTargetName = os.path.join(os.path.dirname(__file__),"ApiClassTest") fileSO = [ { "sourseName":os.path.abspath("../src/api/ApiClass.cpp"), "flagsCompil":"-Wall -c -fPIC", "rezultName" :os.path.join(folderTargetName,"ApiClass.o") }, { "sourseName":os.path.join(folderTargetName,"ApiClassAdapter.cpp"), "flagsCompil":"-Wall -c -fPIC -I../src/api", "rezultName" :os.path.join(folderTargetName,"ApiClassAdapter.o") } ] fileTargetName = os.path.join(folderTargetName,"ApiClass.dll") #====================================================== creteDll.CreateDll(folderTargetName, fileTargetName, fileSO) #====================================================== lib = ctypes.cdll.LoadLibrary(fileTargetName) self.createEmptyApiClass = lib.createEmptyApiClass self.deleteEmptyApiClass = lib.deleteEmptyApiClass self.callEmptyApiClassMethod = lib.callEmptyApiClassMethod self.callEmptyApiClassMethod.restype = ctypes.c_int self.createApiClass = lib.createApiClass self.deleteApiClass = lib.deleteApiClass self.callApiClassMethod = lib.callApiClassMethod self.callApiClassMethod.restype = ctypes.c_int def tearDown(self): self.deleteEmptyApiClass() self.deleteApiClass() def test_var1(self): self.createEmptyApiClass() self.assertEqual(self.callEmptyApiClassMethod(10), 10,'10+0 = 10') self.assertEqual(self.callEmptyApiClassMethod(20), 30,'20+10 = 30') def test_var2(self): self.createApiClass(100) self.assertEqual(self.callApiClassMethod(10), 110,'10+100 = 110') self.assertEqual(self.callApiClassMethod(20), 130,'20+110 = 130')
import unittest loader = unittest.TestLoader() suite = loader.discover(start_dir='.', pattern='*Test.py') runner = unittest.TextTestRunner(verbosity=5) result = runner.run(suite)
python TestRun.py
Source: https://habr.com/ru/post/350952/
All Articles