如何在C/C++中包装Python对象?
要将现有的C或C++功能包装到Python中,有很多选项可用,它们是:使用PyMethodDef和Py_InitModule进行手动包装、SWIG、Pyrex、ctypes、SIP、Boost.Python和pybind1。
使用SWIG模块
让我们以一个C函数为例,然后使用SWIG将其调整为Python。SWIG代表“简单包装器接口生成器”,它能够将C包装到多种语言中,例如Python、PHP、TCL等。
示例
考虑example.c文件中简单的阶乘函数fact()。
/* File : example.c */ #include <example.h> // calculate factorial int fact(int n) { if (n <= 1) return 1; else return n*fact(n-1); }
头文件
int fact(int n);
接口文件
现在,为了将上述C函数添加到Python语言中,您需要编写一个“接口文件”,它是SWIG的输入。
/* example.i */ %module example %{ /* Put header files here or function declarations like below */ extern int fact(int n); %} extern int fact(int n);
创建Python包装器
只需按照以下步骤,我们就可以将C代码包装到Python模块中。
>swig -python example.i
这将创建名为“example_wrap.c”和“example.py”的新文件。“example_wrap.c”文件包含我们原始C代码的膨胀版本,其中包含各种错误处理代码等。“example.py”将在我们的Python脚本中导入。
之后执行以下命令
>gcc -c example.c example_wrap.c \ -I/usr/local/include/python2.7
这将生成位置无关代码,该代码将通过编译“example_wrap.c”和“example.py”文件在共享库中使用。注意:将python2.7替换为您的Python版本。这将生成两个目标文件“example_wrap.o”和“example.o”。
>ld -shared example.o example_wrap.o -o _example.so
最后,我们必须将生成的object文件链接在一起以创建一个共享对象,这类似于Windows中的dll文件。使用上述命令,这将生成一个“_example.so”共享对象文件。现在我们可以通过导入它来测试Python包装器了。
>>> import example >>> example.fact(5) 120
使用Boost库
现在,让我们以一个C++函数为例,然后使用Boost.Python将其包装到Python中。
Boost.Python库用于在C/C++中包装Python对象。Boost Python库是一个用于连接Python和C++的框架。无需使用任何特殊工具,它允许我们快速而无缝地将C++类、函数和对象公开给Python,反之亦然。
它旨在非侵入式地包装C++接口,因此您无需更改C++代码即可进行包装。该库使用高级元编程技术,简化了用户的语法,使包装代码看起来像是一种声明性接口定义语言(IDL)。
示例
让我们来看一个基本的包装器:我们在C++文件中有一个函数“foo”。
char const* foo() { return "Sample,function"; }
然后编写一个Boost.python包装器,以将“foo”函数公开给Python。
#include <boost/python.hpp> BOOST_PYTHON_MODULE(sample) { using namespace boost::python; def("foo",foo); }
从上述设置中,我们构建了一个共享库。现在,Python可以访问生成的DLL。这是一个Python会话示例:
<<< import sample <<< print(sample.foo())
输出
Sample, function
通过使用这个基本的foo函数,我们已经成功地将C++函数共享给了Python。