在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
转载:http://blog.csdn.net/chgaowei/article/details/7467632
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复制给数组成员即可。 |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论