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

第一部分转自 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的头文件
// 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 r
print "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接口也不像这里。但是也没有想到会在哪里,如果哪位大神知道麻烦告诉我,我将来知道了也会在这里更新。

你可能感兴趣的:(个人)