python封装c函数库的调用
主要使用ctypes,具体内容参考https://www.cnblogs.com/yssjun/p/9960479.html
https://blog.csdn.net/weixin_33696106/article/details/92440166
以下内容环境:python2.7。
按照该参考将函数封装成使用系统的库,然后使用ctypes完成库的调用使用。
测试c代码
#include <stdio.h>
extern "C" int Add(int a,int b)
{
return a+b;
}
extern "C" int print_111(int a,int b)
{
printf("hello,111\n");
return a+b;
}
注意要加extern "C“,否则调用时会出现未定义符号的报错。
编库:
gcc -c -fPIC test_c.cc
gcc -shared test_c.o -o test_c.so
调用:
import ctypes
libc = ctypes.cdll.LoadLibrary('./test_c.so')
#libc = ctypes.cdll.LoadLibrary('libc.so.6')
print libc
print libc.Add(1,2)
print libc.print_111(1,2)
如何封装成一个模块?先上一个例子:
c实现:
#include "test.h"
int add(int a,int b)
{
return a+b;
}
test头文件:
int add(int a,int b);
扩展模块c实现:
#include <Python.h>
#include "test.h"
PyObject* wrap_add(PyObject* self, PyObject* args)
{
int n0,n1, result;
if (! PyArg_ParseTuple(args, "ii", &n0, &n1))
return NULL;
printf("n0 = %d\n",n0);
printf("n1 = %d\n",n1);
result = add(n0,n1);
return Py_BuildValue("i", result);
}
static PyMethodDef testMethods[] =
{
{"add", wrap_add, METH_VARARGS, "Add"},
{NULL, NULL}
};
PyMODINIT_FUNC inittest(void)
{
PyObject* m;
m = Py_InitModule("test", testMethods);
}
编译:
gcc -fPIC -shared -o test.so -I/usr/include/python2.7 test.c wrap_test.c -lpython2.7
然后就可以直接将test模块导入执行
import test
print test.add(2,4)
一个典型的python扩展模块,至少包含以下三个部分:
1、导出函数wrap_add,用来把导出函数和C语言函数对应起来,带有两个参数:
参数self只在C函数被实现为内联方法时才被用到,通常为NULL
参数args中包含了python解释器要传给C函数的所有参数,通常使用PyArg_ParseTuble()来获得这些参数值。
所有的导出函数都返回一个PyObject指针,如果对应C函数没有返回值,则需要返回Py_None,并将其引用计算增1.
PyObject* wrap_method(PyObject *self, PyObject *args)
{
Py_INCREF(Py_None);
return Py_None;
}
2、方法列表
由四个部分组成:方法名,导出函数,参数传递方式,方法描述。
方法名是从python解释器中调用该方法时所使用的名字。参数传递方式则规定了python向C函数传递参数的具体形式,可选的两种方式是METH_VARARGS和METH_KEYWORDS,其中METH_VARARGS是参数传递的标准形式,它通过python的元组在python解释器和c函数之间传递参数,若采用METH_KEYWORD方式,则python解释器和C函数之间则通过PYTHON的字典类型在两者之间进行参数传递。
3、初始化函数
所有的python扩展模块都必须要有一个初始化函数,以便python解释器能够对模块进行正确的初始化。python解释器规定所有的初始化函数的函数名都必须以init开头,并加上模块的名字。当python解释器需要导入该模块时,将根据该模块的名称查找相应的初始化函数,一旦找到便进行初始化工作。Py_initModule用来向python解释器注册该模块中所有可以用到的方法。
本文地址:https://blog.csdn.net/azheng_wen/article/details/107664987