欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

python封装c函数库的调用

程序员文章站 2022-03-05 13:21:47
主要使用ctypes,具体内容参考项目中可能会经常用到第三方库,主要是出于程序效率考虑和节约开发时间避免重复造*。无论第三方库开源与否,编程语言是否与当前项目一致,我们最终的目的是在当前编程环境中调用库中的方法并得到结果或者借助库中的模块实现某种功能。这个过程会牵涉到很多东西,本篇文章将简要的介绍一下该过程的一些问题。1.背景多语言混合编程可以弥补某一种编程语言在性能表现或者是功能等方面的不足。虽然所有的高级语言都会最终转换成汇编指令或者最底层的机器指令,但是语言本身之间的千差万别很难一言以蔽之...

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

相关标签: C语言特性学习