Python调用C函数
完全参考CoolShell博客《PYTHON调用C语言函数》
使用Python的ctypes,我们可以直接调用由C编译出来的函数。其实就是调用动态链接库中的函数。为什么要这样做?因为有些时候,我们可能需要一个性能上比较讲究的算法;有些时候我们可以在Python中使用已经有了的现成的被封闭在动态链接库中的函数
比如,下面这样一个用C实现的加法程序
int add(int n1, int n2){
return n1 + n2;
}
如果在Windows下,需要写成下面这样
#include
BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved){
return TRUE;
}
__declspec(dllexport) int add(int n1, int n2){
return n1 + n2;
}
Linux下用以下命令编译
gcc -c -fPIC libtest.c
gcc -shared libtest.o -o libtest.so
Windows下使用以下命令编译
cl -LD libtest.c -libtest.dll
然后在Python中如下使用(Windows的话将libtest.so改为libtest.dll即可)
[root@root test]# python
Python 2.6.6 (r266:84292, Sep 4 2013, 07:46:00)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-3)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from ctypes import *
>>> import os
>>> libtest = cdll.LoadLibrary(os.getcwd() + '/libtest.so')
>>> print libtest.add(100, 10)
110
>>>
Boost::Python粘合C++和Python
Python已经提供了API,用于粘合Python和C。那Boost::Python又是什么?Boost::Python是Python/C API的一个封装(wrapper)。使用Python/C API,你需要在Python和C代码之间传递指针的前后,手动处理指针问题,比如指针不再指向原来的对象时,Boost::Python接管了这个任务,自动处理。此外,Boost::Python是我们能用C++的OOP方式,在Python对象上写操作
比如,对于Python代码y = object_x[i],同样的功能用Python/C API实现,需要这样写
y = PySequence_GetItem(object_x, i);
作为对比,用Boost::Python这样写就好了
y = object_x[i];
Boost::Python使得将我们的C++类输出为Python变得容易,甚至都不需要改变。Boost::Python的设计理念是:用户永远不需要接触PyObject*
以下的事例是在Mac OS平台的实验情况,Windows、Linux还未做研究!
下载、编译安装boost
在浏览器中输入链接http://jaist.dl.sourceforge.net/project/boost/boost/1.55.0/boost_1_55_0.tar.bz2下载boost
解压缩tar zxvf boost_1_55_0.tar.bz2,然后进入文件夹cd boost_1_55_0
运行shell脚本bash bootstrap.sh
如果在当前目录下(比如/Users/xumenger/Desktop/library/boost_1_55_0)运行b2进行编译,那么在对应目录下生成如下内容
image
也可以./b2 install进行安装,执行完毕后头文件在/usr/local/include下、库文件在/usr/local/lib下
C++导出函数
编写C++代码hello.cpp如下
#include
#include
#include
using namespace std;
using namespace boost::python;
void say()
{
cout<
}
BOOST_PYTHON_MODULE(hello)
{
def("say", say);
}
g++使用第三方库编译是如下命令
g++ -fpic -c -L/Users/xumenger/Desktop/library/boost_1_55_0/ -I/usr/include/python2.7 hello.cpp
g++ -shared -L/usr/lib -L/Users/xumenger/Desktop/library/boost_1_55_0/stage/lib -lpython2.7 -lboost_python -o hello.so hello.o
编译结果如下
image
然后将/Users/xumenger/Desktop/library/boost_1_55_0/stage/lib/libboost_python.dylib拷贝到hello.so所在文件夹下
然后在hello.so所在目录启动Python,期间可能遇到ImportError的错误
image
参考unsafe use of relative rpath libboost.dylib when making boost.python helloword demo?,运行以下命令
install_name_tool -change libboost_python.dylib /usr/local/lib/libboost_python.dylib hello.so
otool -L hello.so
然后再在Python命令下执行即可成功!
xumenger-mac:boost xumenger$ python
Python 2.7.10 (default, Feb 7 2017, 00:08:15)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.34)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import hello
>>> hello.say()
Hello World!
>>>
C++导出类
编写程序testclass.cpp如下
#include
#include
#include
using namespace std;
using namespace boost::python;
class person
{
public:
void setname(string str)
{
name_ = str;
}
string getname()
{
return name_;
}
void setage(int age)
{
age_ = age;
}
int getage()
{
return age_;
}
private:
string name_;
int age_;
};
BOOST_PYTHON_MODULE(testclass) //python模块
{
class_("person")
.def("setname", &person::setname)
.def("getname", &person::getname)
.def("setage", &person::setage)
.def("getage", &person::getage)
.add_property("name", &person::getname, &person::setname)
.add_property("age", &person::getage, &person::setage)
;
}
编译程序,得到testclass.so
g++ -fpic -c -L/Users/xumenger/Desktop/library/boost_1_55_0/ -I/usr/include/python2.7 testclass.cpp
g++ -shared -L/usr/lib -L/Users/xumenger/Desktop/library/boost_1_55_0/stage/lib -lpython2.7 -lboost_python -o testclass.so testclass.o
执行下面命令,防止ImportError
install_name_tool -change libboost_python.dylib /usr/local/lib/libboost_python.dylib testclass.so
otool -L testclass.so
然后开启Python进行测试
xumenger-mac:boost xumenger$ python
Python 2.7.10 (default, Feb 7 2017, 00:08:15)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.34)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import testclass
>>> p = testclass.person()
>>> p.setname("xumenger")
>>> p.setage(24)
>>> print p.name
xumenger
>>> print p.age
24
>>>
标签: Python
顶一下
(0)
0%
踩一下
(0)
0%