python脚本调用c/c++库,以opencv的python接口为例

来源:互联网 发布:推荐算法有哪些 编辑:程序博客网 时间:2024/05/01 21:39
第一部分转自 http://blog.csdn.net/yjfkpyu/article/details/3941878
Python开发效率高,运行效率低。而c/c++恰恰相反。因此在python脚本中调用c/c++的库,对python进行扩展,是很有必要的。使用python api,http://www.python.org/doc/,需要安装python-dev。
test.c文件如下
#include <Python.h>//包含python的头文件// 1 c/cpp中的函数int my_c_function(const char *arg){  int n = system(arg);  return n;}// 2 python 包装static PyObject * wrap_my_c_fun(PyObject *self, PyObject *args){  const char * command;  int n;  if (!PyArg_ParseTuple(args, "s", &command))//这句是把python的变量args转换成c的变量command    return NULL;  n = my_c_function(command);//调用c的函数  return Py_BuildValue("i", n);//把c的返回值n转换成python的对象}// 3 方法列表static PyMethodDef MyCppMethods[] = {  //MyCppFun1是python中注册的函数名,wrap_my_c_fun是函数指针  {"MyCppFun1", wrap_my_c_fun, METH_VARARGS, "Execute a shell command."},  {NULL, NULL, 0, NULL} };// 4 模块初始化方法PyMODINIT_FUNC initMyCppModule(void){  //初始模块,把MyCppMethods初始到MyCppModule中  PyObject *m = Py_InitModule("MyCppModule", MyCppMethods);  if (m == NULL) return;}

test.py文件如下
import MyCppModule//导入python的模块(也就是c的模块,注意so文件名是MyCppModule)r = MyCppModule.MyCppFun1("ls -l")//调用print rprint "OK"

从这里开始是我个人的分析

原来如此!
首先我们得现有一个c/c++函数,这个c函数被一个它的wrapper调用,wrapper又称为导出函数,这里是wrap_my_c_fun。这一步实际上就是把python类型的输入转成c类型的输入并传入c函数,并把c函数中返回的c类型的输出转换成python类型的输出返回。而再上一层,是一个方法列表,里面保存的全部是函数指针,其中METH_VARARGS是参数传递的标准形式,它通过Python的元组在Python解释器和C函数之间传递参数,我们把wrap_my_c_fun放在这个列表当中。最后,我们在初始化函数中初始化一个MyCppModule的模块。这样,import的时候我们就已经有了my_c_function的python模块。MyCppModule了。


现在再看opencv是如何做的
首先,在/home/intel/Documents/Install-OpenCV-master/Ubuntu/2.4/OpenCV/opencv-2.4.9/modules/python/src2/cv2.cpp的最后有一个函数
void initcv2() 这个就相当于上面的initMyCppModule。里面调用了PyObject* m = Py_InitModule(MODULESTR, methods); 相当于Py_InitModule("MyCppModule", MyCppMethods);其中MODULESTR=cv2,也就是我们将来要import的库的名字。而methods则是函数列表的名字。
函数列表也在该文件中
static PyMethodDef methods[] = {#include "pyopencv_generated_func_tab.h"  {"createTrackbar", pycvCreateTrackbar, METH_VARARGS, "createTrackbar(trackbarName, windowName, value, count, onChange) -> None"},  {"setMouseCallback", (PyCFunction)pycvSetMouseCallback, METH_KEYWORDS, "setMouseCallback(windowName, onMouse [, param]) -> None"},  {NULL, NULL},};相当于static PyMethodDef MyCppMethods[]

再往里就是pycvCreateTrackbar和pycvSetMouseCallback,这里没有继续往里找,原因是这里并不是我们真正执行opencv的函数的时候走的路径。
实际上我们的函数走的是PyObject* m = Py_InitModule(MODULESTR, methods);后面的一句话PyObject* cv_m = init_cv();
因为opencv中有cv和cv2,这里实际上是cv2的模块初始化函数调用了cv的模块初始化函数,主要内容都在这儿呢。


init_cv的定义在/home/intel/Documents/Install-OpenCV-master/Ubuntu/2.4/OpenCV/opencv-2.4.9/modules/python/src2/cv2.cv.hpp下
init_cv函数中有这样一句话,这句话是cv2.cv这个module的初始化 m = Py_InitModule(OLD_MODULESTR, old_methods);


我们看函数列表old_methods
static PyMethodDef old_methods[] = {#if PYTHON_USE_NUMPY    {"fromarray", (PyCFunction)pycvfromarray, METH_KEYWORDS, "fromarray(array [, allowND]) -> CvMat"},#endif  {"FindDataMatrix", pyfinddatamatrix, METH_VARARGS},  {"temp_test", temp_test, METH_VARARGS},#include "generated1.i"  {NULL, NULL},};
目前我就追踪到这里,貌似opencv的python接口也不像这里。但是也没有想到会在哪里,如果哪位大神知道麻烦告诉我,我将来知道了也会在这里更新。

0 0