python封装c函数库的调用

2022-07-31,,,

主要使用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

《python封装c函数库的调用.doc》

下载本文的Word格式文档,以方便收藏与打印。