0、背景
用熟了python后,再使用C++的就觉得很不方便,因为每一次编程完毕都要编译一遍。殊不知,有些情况下,在C++程序中配合使用python程序反而很方便。
比如。
在一个C/C++应用程序中,我们一般用一组插件来实现一些具有统一接口的功能。这个插件一般都是使用动态链接库来实现的。如果插件的变化比较频繁,我们可以使用 Python 来代替动态链接库形式的插件。这样可以很方便地根据需求的变化改写脚本代码(进行不同的数据处理),而不是必须重新编译链接二进制的动态链接库。
// main.cppint main(int argc, char *argv[]) {// 初始化python解释器.C/C++中调用Python之前必须先初始化解释器Py_Initialize();// 执行一个简单的执行python脚本命令PyRun_SimpleString("print('hello world')\n");// 撤销Py_Initialize()和随后使用Python/C API函数进行的所有初始化Py_Finalize();return 0;}
编译方法:
g++ main.cpp -I /usr/include/python3.5 -l python3.5m -o test(注意这里要替换为你实际使用的 python 库和头文件路径,可以使用 whereis python 指令找到)。
本处将上述编译的代码写成了一个简单的shell脚本。文件及文件内容汇总如下:

运行后输出如下:

using namespace std;int main(){// 1、初始化python接口Py_Initialize();if(!Py_IsInitialized()){cout << "python init fail" << endl;return 0;}// 2、初始化python系统文件路径,保证可以访问到 .py文件PyRun_SimpleString("import sys");PyRun_SimpleString("sys.path.append('./script')");// 3、调用python文件名,不用写后缀PyObject* pModule = PyImport_ImportModule("sayhello");if( pModule == NULL ){cout <<"module not found" << endl;return 1;}// 4、调用函数PyObject* pFunc = PyObject_GetAttrString(pModule, "say");if( !pFunc || !PyCallable_Check(pFunc)){cout <<"not found function add_num" << endl;return 0;}//PyObject_CallObject(pFunc, NULL);// 5、结束python接口初始化Py_Finalize();return 0;}
def say():print("hello, limanman.")


上述只是演示了下,C++中如何调用python的库和库里的函数,如下将演示如何进行参数传递。
首先修改main.cpp的代码如下所示:
using namespace std;int main(){Py_Initialize(); //1、初始化python接口//初始化使用的变量PyObject* pModule = NULL;PyObject* pFunc = NULL;PyObject* pName = NULL;//2、初始化python系统文件路径,保证可以访问到 .py文件PyRun_SimpleString("import sys");PyRun_SimpleString("sys.path.append('./')");//3、调用python文件名。当前的测试python文件名是 myadd.py// 在使用这个函数的时候,只需要写文件的名称就可以了。不用写后缀。pModule = PyImport_ImportModule("myadd");//4、调用函数pFunc = PyObject_GetAttrString(pModule, "AdditionFc");//5、给python传参数// 函数调用的参数传递均是以元组的形式打包的,2表示参数个数// 如果AdditionFc中只有一个参数时,写1就可以了PyObject* pArgs = PyTuple_New(2);// 0:第一个参数,传入 int 类型的值 2PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", 2));// 1:第二个参数,传入 int 类型的值 4PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", 4));// 6、使用C++的python接口调用该函数PyObject* pReturn = PyEval_CallObject(pFunc, pArgs);// 7、接收python计算好的返回值int nResult;// i表示转换成int型变量。// 在这里,最需要注意的是:PyArg_Parse的最后一个参数,必须加上“&”符号PyArg_Parse(pReturn, "i", &nResult);cout << "return result is " << nResult << endl;//8、结束python接口初始化Py_Finalize();}
# myadd.pydef AdditionFc(a, b):print("Now is in python module")print("{} + {} = {}".format(a, b, a+b))return a + b

# myadd.pydef AdditionFc(a, b):print("Now is in python module")print("{} + {} = {}".format(a, b, a+b))print("{} * {} = {}".format(a, b, a*b))return a + b
