python结构体数组传出接收c动态库 swig_使用swig为python添加c扩展总结

1、  可以使用swig来创建c 的扩展程序,非常方便。目前没有时间研究内部机制,先暂时使用,后面在研究吧。

2、  swig使用步骤:为库的头文件建立.i文件:

%{

/* Includes theheader in the wrapper code */

#include"code.h"

#include"sip.h"

%}

/* Parse theheader file to generate wrappers */

%include"code.h"

%include"sip.h"

3、  使用swig命令生成py脚本及对应的C文件:swig –python sip.i。

4、  将生成的c源文件放到c扩展库中进行编译。

5、  这里有一个要注意:生成的动态链接库,必须是_sip.so,否则无法调用。swig是写死的。_sip.so需要拷贝到:/usr/local/lib/python2.7/site-packages/路径下。

6、  Makefile文件中,对于库引用的其他的库,必须显示的指出,否则Python无法找到对应的库。

7、  如何在c的扩展库中调用Python的函数——将c扩展库的回调函数设置为python函数:

swig是不支持直接在c的扩展库中调用Python函数的。它只支持将C的接口作为回调函数设置给c的库。

实现这个功能需要利用Python的c API和ctypes来实现。

Python c 的api包含一系列的函数:

PyCallable_Check:检查对象是否可调用;

PyArg_ParseTuple:解析参数列表,将Python参数解析为c;

PyEval_CallObject:调用对象;

Py_BuildValue:将c变量打包为Python的参数对象。

好了,有这些就足够了。

假设c库中有一个设置回调函数接口:

void set_callback_fun(void(*fun)(int, int , int))

{

}

下面是c扩展库中要添加的代码:

//全局变量,保存Python中要回调的可调用对象。

static PyObject*gCallbackFun = NULL;

//调用上面函数设置的python脚本函数

//Python可调用对象的转换函数,转化为C的调用方式

static voidcallbacfun(int type,int chn,int dataType)

{

PyObject* pArgs = NULL;

PyObject* pRetVal = NULL;

int   nRetVal = 0;

pArgs = Py_BuildValue("(i, i,i)", type, chn, dataType);//将c的参数转化为Python的参数对象

pRetVal = PyEval_CallObject(gCallbackFun,pArgs);//调用Python的可调用对象。

Py_DECREF(pArgs);

Py_DECREF(pRetVal);

}

/// set_callback_fun函数的包装函数

static PyObject*wrap_set_callback_fun(PyObject *dummy, PyObject *args)

{

PyObject *temp = NULL;

if (PyArg_ParseTuple(args, "O:set_callback_fun",&temp)) {//获取Python对象

if (!PyCallable_Check(temp)) {//检查对象是否可以调用

PyErr_SetString(PyExc_TypeError,"parameter must be callable");

}

Py_XINCREF(temp);         /* Add a reference to new callback */

Py_XDECREF(gCallbackFun); /* Dispose ofprevious callback */

gCallbackFun = temp;       /* 保存回调对象 */

}

set_callback_fun(callbacfun);//注意,这里掉一下包,用一个C的函数注册到c库中。

return Py_BuildValue("i",(gCallbackFun == NULL) ? 0 : 1);

}

注意:如果对象不可调用,会段错误。后面要解决一下。

Python代码:

CBFUNC  =CFUNCTYPE(c_int, c_int, c_int, c_int)//创建一个c函数类型的对象工厂,该函数返回值为int,有三个入参,都为int。

callbakFunc = CBFUNC(pyFun)//根据Python可调用对象生成函数。

set_callback_fun(callbakFunc)//设置回调函数

注意:pyFun必须要有返回值。否则会报异常。

另外,我发现,不用CFUNCTYPE来生产c回调函数,直接用pyFun,也是可以的。至于区别,后面在研究一下吧,要写代码了。

几个异常问题:1、一个可以使用CFUNCTYPE,但是一个一使用它就段错误。2、回调函数可以不返回值,也是可以的。但是一个不返回就不可以。

在Python中使用c扩展时向C传递数组:

8、  如果一个函数的参数是一个数组(指针),Python如何传递?下面的方法是可以直接传递列表。把这个加到.i文件中。

%{

static intconvert_darray(PyObject *input, int *ptr, int size) {

int i;

if (!PySequence_Check(input)) {

PyErr_SetString(PyExc_TypeError,"Expecting a sequence");

return 0;

}

if (PyObject_Length(input) != size) {

PyErr_SetString(PyExc_ValueError,"Sequencesize mismatch");

return 0;

}

for (i =0; i < size; i++) {

PyObject *o =PySequence_GetItem(input,i);

if (!PyFloat_Check(o)) {

Py_XDECREF(o);

PyErr_SetString(PyExc_ValueError,"Expecting a sequence offloats");

return 0;

}

ptr[i] = PyFloat_AsDouble(o);

Py_DECREF(o);

}

return 1;

}

%}

%typemap(in) int[ANY](int temp[$1_dim0]) {

if (!convert_darray($input,temp,$1_dim0)) {

return NULL;

}

$1 = &temp[0];

}

9、  如果一个结构体中有一个int类型数组,应该如何赋值?

在.i中增加下面代码:

%include"carrays.i"

%array_class(int,intArray);

在Python中申请数组:

a = intArray(10),将A复制给数组成员即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值