python调用c++ ctype list传数组或者返回数组的方法
示例1:
pycallclass.cpp:
#include <iostream> using namespace std; typedef unsigned char byte; #define max_count 20 struct tagoutcardresult_py { byte cbcardcount; byte cbresultcard1; byte cbresultcard2; byte cbresultcard3; byte cbresultcard4; byte cbresultcard5; byte cbresultcard6; byte cbresultcard7; byte cbresultcard8; byte cbresultcard9; byte cbresultcard10; byte cbresultcard11; byte cbresultcard12; byte cbresultcard13; byte cbresultcard14; byte cbresultcard15; byte cbresultcard16; byte cbresultcard17; byte cbresultcard18; byte cbresultcard19; byte cbresultcard20; }; struct tagoutcardresult { byte cbcardcount; byte cbresultcard[max_count]; void clear() { cbcardcount = 0; for (int nidx = 0;nidx < max_count;++nidx) { cbresultcard[nidx] = 0; } } void topy(tagoutcardresult_py* ppy) { cout<<"topy function begin"<<endl; ppy->cbcardcount = cbcardcount; cout<<"topy function 1"<<endl; ppy->cbresultcard1 = cbresultcard[1 - 1]; cout<<"topy function 2"<<endl; ppy->cbresultcard2 = cbresultcard[2 - 1]; ppy->cbresultcard3 = cbresultcard[3 - 1]; ppy->cbresultcard4 = cbresultcard[4 - 1]; ppy->cbresultcard5 = cbresultcard[5 - 1]; ppy->cbresultcard6 = cbresultcard[6 - 1]; ppy->cbresultcard7 = cbresultcard[7 - 1]; ppy->cbresultcard8 = cbresultcard[8 - 1]; ppy->cbresultcard9 = cbresultcard[9 - 1]; ppy->cbresultcard10 = cbresultcard[10 - 1]; ppy->cbresultcard11 = cbresultcard[11 - 1]; ppy->cbresultcard12 = cbresultcard[12 - 1]; ppy->cbresultcard13 = cbresultcard[13 - 1]; ppy->cbresultcard14 = cbresultcard[14 - 1]; ppy->cbresultcard15 = cbresultcard[15 - 1]; ppy->cbresultcard16 = cbresultcard[16 - 1]; ppy->cbresultcard17 = cbresultcard[17 - 1]; ppy->cbresultcard18 = cbresultcard[18 - 1]; ppy->cbresultcard19 = cbresultcard[19 - 1]; ppy->cbresultcard20 = cbresultcard[20 - 1]; cout<<"topy function end"<<endl; } }; class testlib { public: void display(tagoutcardresult& ret); }; void testlib::display(tagoutcardresult& ret) { ret.cbcardcount = 3; ret.cbresultcard[0] = 1; ret.cbresultcard[1] = 50; ret.cbresultcard[2] = 100; cout<<"first display aaa "; cout<<"hello "; cout<<"world "; } extern "c" { testlib ogamelogic; void display(tagoutcardresult_py* ret_py) { tagoutcardresult oret; ogamelogic.display(oret); cout<<"before topy"<<endl; oret.topy(ret_py); cout<<"after topy"<<endl; cout<<"in cpp:ret_py->cbcardcount:"<<ret_py->cbcardcount<<endl; cout<<"in cpp:ret_py->cbresultcard1:"<<ret_py->cbresultcard1<<endl; cout<<" this:" << ret_py << endl; } }
编译脚本:
g++ -o libpycallclass.so -shared -fpic pycallclass.cpp -i/usr/include/python2.6 -l/usr/lib64/python2.6/config
game.py调用部分。类声明:
import ctypes class tagoutcardresult_py(ctypes.structure): _fields_ = [("cbcardcount", ctypes.c_ubyte), \ ("cbresultcard1", ctypes.c_ubyte), \ ("cbresultcard2", ctypes.c_ubyte), \ ("cbresultcard3", ctypes.c_ubyte), \ ("cbresultcard4", ctypes.c_ubyte), \ ("cbresultcard5", ctypes.c_ubyte), \ ("cbresultcard6", ctypes.c_ubyte), \ ("cbresultcard7", ctypes.c_ubyte), \ ("cbresultcard8", ctypes.c_ubyte), \ ("cbresultcard9", ctypes.c_ubyte), \ ("cbresultcard10", ctypes.c_ubyte), \ ("cbresultcard11", ctypes.c_ubyte), \ ("cbresultcard12", ctypes.c_ubyte), \ ("cbresultcard13", ctypes.c_ubyte), \ ("cbresultcard14", ctypes.c_ubyte), \ ("cbresultcard15", ctypes.c_ubyte), \ ("cbresultcard16", ctypes.c_ubyte), \ ("cbresultcard17", ctypes.c_ubyte), \ ("cbresultcard18", ctypes.c_ubyte), \ ("cbresultcard19", ctypes.c_ubyte), \ ("cbresultcard20", ctypes.c_ubyte)]
game.py调用部分。具体调用:
import ctypes so = ctypes.cdll.loadlibrary lib = so("./libpycallclass.so") error_msg('display(\)') ret = tagoutcardresult_py(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) error_msg("before lib.display(ctypes.byref(ret))") lib.display(ctypes.byref(ret)) error_msg("after lib.display(ctypes.byref(ret))") error_msg('#######################################################################################') error_msg(ret) error_msg(ret.cbcardcount) error_msg(ret.cbresultcard1) error_msg(ret.cbresultcard2) error_msg(ret.cbresultcard3) error_msg(type(ret))
传入一个结构体,使用引用返回,回到python中打印出来结果是对的。
这样就可以传入,可以传出了。
示例1end#########################################################################
示例2:
pycallclass.cpp:
#include <iostream> using namespace std; typedef unsigned char byte; #define max_count 20 #if defined(win32)||defined(windows) #define dll_export __declspec(dllexport) #else #define dll_export #endif struct bytearray_20 { byte e1; byte e2; byte e3; byte e4; byte e5; byte e6; byte e7; byte e8; byte e9; byte e10; byte e11; byte e12; byte e13; byte e14; byte e15; byte e16; byte e17; byte e18; byte e19; byte e20; }; struct bytearray_20_3 { bytearray_20 e1; bytearray_20 e2; bytearray_20 e3; }; struct bytearraynew_20_3 { byte e[3][20]; }; class testlib { public: void logicfunc(bytearray_20_3& ret); void logicfuncnew(bytearraynew_20_3& ret); }; void testlib::logicfunc(bytearray_20_3& ret) { ret.e1.e1 = 3; ret.e1.e2 = 1; ret.e1.e3 = 50; ret.e2.e1 = 100; ret.e2.e2 = 200; ret.e2.e3 = 20; cout<<"testlib::logicfunc"<<endl; } void testlib::logicfuncnew(bytearraynew_20_3& ret) { ret.e[0][0] = 31; ret.e[0][1] = 11; ret.e[0][2] = 51; ret.e[1][0] = 101; ret.e[1][1] = 201; ret.e[1][2] = 21; cout << "testlib::logicfuncnew" << endl; } extern "c" { testlib ogamelogic; void dll_export display(bytearray_20_3* pret) { cout<<"cpp display func begin"<<endl; ogamelogic.logicfunc(*pret); cout<<"cpp display func end"<<endl; } void dll_export display2(bytearraynew_20_3* pret) { cout << "cpp display2 func begin" << endl; ogamelogic.logicfuncnew(*pret); cout << "cpp display2 func end" << endl; } }
pycallclass.py:
import ctypes def error_msg(str): print str class bytearray_20(ctypes.structure): _fields_ = [\ ("e1", ctypes.c_ubyte), \ ("e2", ctypes.c_ubyte), \ ("e3", ctypes.c_ubyte), \ ("e4", ctypes.c_ubyte), \ ("e5", ctypes.c_ubyte), \ ("e6", ctypes.c_ubyte), \ ("e7", ctypes.c_ubyte), \ ("e8", ctypes.c_ubyte), \ ("e9", ctypes.c_ubyte), \ ("e10", ctypes.c_ubyte), \ ("e11", ctypes.c_ubyte), \ ("e12", ctypes.c_ubyte), \ ("e13", ctypes.c_ubyte), \ ("e14", ctypes.c_ubyte), \ ("e15", ctypes.c_ubyte), \ ("e16", ctypes.c_ubyte), \ ("e17", ctypes.c_ubyte), \ ("e18", ctypes.c_ubyte), \ ("e19", ctypes.c_ubyte), \ ("e20", ctypes.c_ubyte)] class bytearray_20_3(ctypes.structure): _fields_ = [\ ("e1", bytearray_20), \ ("e2", bytearray_20), \ ("e3", bytearray_20)] def __init__(self): self.aaa = 123 self.bbb = [1, 2, 3, 4, 5] self.ccc = "alksdfjlasdfjk" def test(self): self.aaa = 123 self.bbb = [1, 2, 3, 4, 5] self.ccc = "alksdfjlasdfjk" self.e1.e1 = 5 self.e1.e2 = 20 so = ctypes.cdll.loadlibrary lib = so("./libpycallclass.dll") print('display()') ret = bytearray_20_3() ret.test() error_msg(ret.e1.e1) error_msg(ret.e1.e2) print("before lib.display(ctypes.byref(ret))") lib.display(ctypes.byref(ret)) print("after lib.display(ctypes.byref(ret))") print('#######################################################################################') print(ret) error_msg(ret.e1) error_msg(ret.e2) error_msg(ret.e3) error_msg(ret.e1.e1) error_msg(ret.e1.e2) error_msg(ret.e1.e3) error_msg(ret.e2.e1) error_msg(ret.e2.e2) error_msg(ret.e2.e3) error_msg(type(ret)) print("before lib.display2(ctypes.byref(ret))") lib.display2(ctypes.byref(ret)) print("after lib.display2(ctypes.byref(ret))") print('#######################################################################################') print(ret) error_msg(ret.e1) error_msg(ret.e2) error_msg(ret.e3) error_msg(ret.e1.e1) error_msg(ret.e1.e2) error_msg(ret.e1.e3) error_msg(ret.e2.e1) error_msg(ret.e2.e2) error_msg(ret.e2.e3) error_msg(type(ret)) ret.test() error_msg(ret.e1.e1) error_msg(ret.e1.e2)
g++:
g++ -o libpycallclass.so -shared -fpic pycallclass.cpp -i/usr/include/python2.6 -l/usr/lib64/python2.6/config
windows:
新建一个dll工程,把pycallclass.cpp加进去,编译成dll就ok了。
千万注意python的运行时是32位的还是64位的,dll或者so必须和它对应。
python类可以嵌套使用,继承ctypes.structure,部分成员是_fields_里定义的,部分成员在__init__里定义,这样的类也可以ctypes.byref(self)传进c++去,传的是指针,传入传出就都ok了。
注意示例2中bytearraynew_20_3的用法,python中是定义了20个变量,c++中是直接一个二维数组。内存结构是一致的,所以可以直接这样使用。注意类型和长度必须一致,否则可能会内存访问越界。
以上这篇python调用c++ ctype list传数组或者返回数组的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。