因为python的内核就是c语言写的,所以python和c、c++的相互调用便是理所当然了。
1. #include<Python.h>
首先,需要在被调用的c++代码中加入
#include<Python.h>
这需要在系统中安装python-dev这个额外的包才能有Python.h。
安装命令如下(我们服务器上python版本是2.7.5,所以plugin包选择了python2.7-dev,根据自己情况调整:
sudo apt-get install python2.7-dev
2. extern "C"
加入 #include<Python.h> 后还需要将c++代码中允许python调用的函数/类的成员函数打包成python的module,写了一个小例子TestFact.cpp如下:
#include <Python.h>
#include <string>
using namespace std;
class TestFact{
public:
TestFact(){}
~TestFact(){}
int fact(int n);
string prints(void);
};
int TestFact::fact(int n)
{
return n+10;
}
string TestFact::prints()
{
string str="Today is not a sunny day!";
return str;
}
extern "C"
int fact(int n)
{
TestFact t;
return t.fact(n);
}
extern "C"
string prints()
{
TestFact t;
string str=t.prints();
return str;
}
在这个例子中创建了一个类TestFact, 并且定义了两个成员函数。 之后将两个成员函数分别包装。
注意:一定要加上 extern "C", 否则会报错。
3.生成so文件
下一步是将c++代码生成*.so文件。
(1).若用g++生成,用如下命令
g++ -fPIC -shared -o TestFact.so TestFact.cpp -I/usr/include/python2.7 -I/usr/lib/python2.7/config
(2).若用cmake生成,代码如下
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)注意:Python.h 的文件路径需要手动设置,不在系统默认文件夹内,其地址为/usr/include/python2.7
PROJECT(TESTFACT)
SET(CMAKE_BUILD_TYPE Debug)
SET(COMPILER "gpp")
SET(LIB_TESTFACT TESTFACT)
INCLUDE_DIRECTORIES("/usr/include/python2.7")
INCLUDE_DIRECTORIES("/usr/lib//python2.7/config")
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
SET(SRC_LIST TestFact.cpp)
ADD_LIBRARY(${LIB_TESTFACT} SHARED ${SRC_LIST})
此外,还需要设置python库的共享链接库地址,即/usr/lib//python2.7/config。
这些路径也应根据具体情况有所改变
成功生成后会得到 libTESTFACT.so 位于 项目路径/build/bin下
4. python调用
最后一步是使用python调用 .so文件。 写了一个小例子如下:
#!/usr/bin/env python
import ctypes
d=ctypes.CDLL("./cpl2.so")
c=d.prints()
print c
print d.fact(10)
运用ctypes库的功能,d是一个ctypes.CDLL的对象,指向cpl2.so这个共享库。
若要调用cpl2.so中已包装好的module,直接调用 d.module名 即可。
5.多个文件的调用
若要一次性调用多个文件,有两种方法
(1).生成 .so 文件的时候将多个c++文件分别生成各自的 .so文件。
(2).将多个c++文件生成同一个.so文件,这用g++或cmake都很容易实现. 需要注意的是,同一个.so文件中包装的module名不能重复。
后记: 除了ctypes以外, 在python中调用c++还可以运用boost库或利用swig来实现,这两种方法还有待学习。