编译环境是centos7,ctypes的一些基本用法可以随便百度一下都能找到很多资料,但是很少有提到怎么调用c++函数或者类方法的文章,本文主要介绍的内容包括:
1、怎样调用c++的函数和类方法
2、向c函数中传入回调函数的方法
一、python的ctypes调用c++函数和方法
常规的ctypes调用c函数的方法
//ctest.c #includeint func(int a, int b) { int res = a + b; printf("%d + %d = %dn", a, b, res); return res; }
c文件编译:gcc ctest.c -shared -fPIC -o libctest.so
注意:不要加 -c
#pycallc.py import ctypes ll = ctypes.cdll.LoadLibrary lib = ll("./libctest.so") lib.func(2, 3)
运行python脚本:python3 pycallc.py
结果如下,能正确运行:
python调用cpp函数:
//cpptest.cpp --> libcpptest.cpp #includeint func(int a, int b) { int res = a + b; printf("%d + %d = %dn", a, b, res); return res; }
编译指令:g++ cpptest.cpp -shared -fPIC -o libcpptest.so
#pycallcpp.py import ctypes ll = ctypes.cdll.LoadLibrary lib = ll("./libcpptest.so") lib.func(2, 3)
执行 python3 pycallcpp.py会报错,显示找不到func函数,原因正是g++编译器将函数的名字加了前后缀,使用nm命令查看,nm libcpptet.so | grep func 可以看到func的函数名变成_Z4funcii,ii正是func函数的两个int参数
改变python代码里的函数名,然后python代码就能正确的调用c++函数了。
#pycallcpp.py import ctypes ll = ctypes.cdll.LoadLibrary lib = ll("./libcpptest.so") lib._Z4funcii(2, 3)
如果使用函数的话使用extern “C”,也可以达到效果,就是让g++编译器使用c的函数编译方式,也就是不加前后缀,但是这种方式c++的函数重载功能就没有了,怀着好奇心,继续研究怎么让python调用c++的类方法。
//cpptest.cpp --> libcpptest.so #includeclass TEST { public: static int func(int a, int b) { int res = a + b; printf("%d + %d = %dn", a, b, res); return res; } }; //foo()函数在python中不调用 void foo() { TEST t; t.func(1, 2); }
使用nm命令查看func函数名变成了什么:nm libcpptest.so | grep func
foo()函数的存在是因为其内部初始化了一个类,并调用了func()方法,使得编译出的动态库能生成func的函数名,如果没有此函数,使用nm命令是找不到这个函数的,具体原因我还没弄清楚,期待有大神留言交流,第二个要注意的点是func()函数必须声明为static,因为类的非静态函数的第一个参数是this指针,c++的类无法在python中传递
#pycallcpp.py import ctypes ll = ctypes.cdll.LoadLibrary lib = ll("./libcpptest.so") lib._ZN4TEST4funcEii(2, 3)
二、回调函数传递的问题
1、python中写回调函数作为参数传递给c函数
//ctest.c --> libctest.so #includetypedef int (*ADD)(int, int); int func(ADD f, int a, int b) { int sum = f(a, b); printf("sum = %dn", sum); return sum; }
from ctypes import * ll = cdll.LoadLibrary lib = ll("./libctest.so") def callback(a, b): return a + b; cfunctype = CFUNCTYPE(c_int, c_int, c_int) #第一个是函数返回值,后面两个是参数列表 add = cfunctype(callback) lib.func(add, 5, 6)
2、在c中写回调函数
//ctest.c --> libctest.so #includetypedef int (*ADD)(int, int); int func(ADD f, int a, int b) { int sum = f(a, b); printf("sum = %dn", sum); return sum; } int add(int a, int b) { return a + b; }
from ctypes import * ll = cdll.LoadLibrary lib = ll("./libctest.so") lib.func(lib.add, 5, 6)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)