guxch的专栏

路漫漫其修远兮,吾将上下而求索

python与C C++的交互(二)

五.在python环境中调用C/C++代码

前面是两点基础,这节说明在python环境中调用C/C++代码。

大致有两种方式:

1.       将c/c++代码编译成(操作系统)标准的动态库,在python中“引用”后调用

2.       将c/c++代码写成python扩展库,就如同python的内置的标准库一样,正常引用后调用

第一种方式比较简单,下面是一个简单示例。

C/C++代码(文件名为mm.cpp)

#include <stdio.h>

#ifdef __cplusplus
extern "C" 
#endif
void myconcate(char *dest, char *src, int i, double f)
{
	sprintf(dest, "string:%s, integer:%d, float:%f", src, i, f);
}

注意,C++代码必须在函数前加 extern “C”。编译成动态库libmm.so

gcc mm.cpp -fPIC - shared  -o libmm.so

 Python代码

import ctypes

mm=ctypes.CDLL("./libmm.so")
dest=ctypes.create_string_buffer(200)
mm.myconcate(dest,b"This",100,ctypes.c_double(12.3))
print(repr(dest.raw))

这种方式二者的“独立性”较高,为做接口而额外的付出少,缺点是从python的角度看,这种方法比较生硬,如果对c/c++库的引用仅限于特定的项目,可采用。

第二种方式就麻烦一些,本质上是写一个python库。

C/C++代码(文件名为cfun.cpp)

PyObject*  op_minus(PyObject *self, PyObject *args)
{
int a,b;
if(!PyArg_ParseTuple(args, "ii",&a,&b))  return NULL;
    return PyLong_FromLong(a-b);
//如果是正常下返回void, 使用下面代码(注:C函数应“拥有”对象的引用,然后传递给python调用者)
//Py_INCREF(Py_None);
//return Py_None;
}
PyMethodDef cmethods[] =
{
    {"minus", op_minus, METH_VARARGS, "Return the difference of the integers."},
    {NULL, NULL, 0, NULL}   // Sentinel
};

 PyModuleDef cmodule=
 {
PyModuleDef_HEAD_INIT,
" cmodule ",    // name of module

NULL,  // module documentation, may be NULL
-1, // size of per-interpreter state of the module, or -1 if the module keeps state in global variables.
 cmethods,
  };
#ifdef __cplusplus
extern "C" 
#endif
PyObject* PyInit_cmodule(void)
{
    return PyModule_Create(&cmodule);
}

代码中,cmethods是函数(方法)表,METH_VARARGS表示函数解析参数的方法:python采用tuple表,C采用PyArg_ParseTuple(),另外一种方式是METH_VARARGS| METH_KEYWORDS,此时,C函数有第三个参数,形式如下:

cfun(PyObject *self, PyObject *args, PyObject * kw)

kw是一个关键字的字典,C采用PyArg_ParseTupleAndKeywords()来解析参数

cmodule是模块表,模块表需要在模块初始化时告诉解释器,注意,模块初始化函数名遵循PyObject* PyInit_XX(void),其中XX是模块名。

C的代码比较长,实现的逻辑在op_minus中,其余应该是套路。

 为编译和安装扩展库,可利用python本身的distutils包,代码如下(保存为setup.py):


from distutils.core import setup, Extension
module1 = Extension(name=' cmodule', sources = ['cfun.cpp'],language='c++')
setup (name = 'PackageName',
       version = '1.0',
       description = 'This is a demo package',
       ext_modules = [module1])

如果编译出现错误,module1的定义中,添加include_dirs(头文件目录),define_macros(预定义项),library_dirs(库目录),libraries(库),extra_compile_args(编译选项),extra_link_args(链接选项)等,设置与C/C++环境中一致。

编译命令如下:

python setup.py build

安装命令如下:

python setup.py install

Python代码

import cmodule
def minus(a,b):
    c = cmodule.minus(a,b)
    return c
minus(5,3)


阅读更多
文章标签: Python C/C++ 互操作
个人分类: Linux C/C++ python
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

不良信息举报

python与C C++的交互(二)

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭