C++调用Python用法总结
项目中需要用到C++调用Pyhton文件中的函数,因此总结了一下常用的使用的方法。
环境
Pyhton2.7
在C++程序中需要应用Python的头文件,在VisualStudio环境中调试的时候使用的是Debug模式,而Python的配置文件pyconfig.h(C:\Python27\include\pyconfig.h)文件中声明了当在Debug模式下调试时,需要引用python27_d.lib的库文件,但是在安装Python的时候并无此文件。
/* For an MSVC DLL, we can nominate the .lib files used by extensions */
#ifdef MS_COREDLL
# ifndef Py_BUILD_CORE /* not building the core - must be an ext */
# if defined(_MSC_VER)
/* So MSVC users need not specify the .lib file in
their Makefile (other compilers are generally
taken care of by distutils.) */
# ifdef _DEBUG
# pragma comment(lib,"python27_d.lib")/*Debug模式下应用python27_d.lib文件*/
# else
# pragma comment(lib,"python27.lib")
# endif /* _DEBUG */
# endif /* _MSC_VER */
# endif /* Py_BUILD_CORE */
#endif /* MS_COREDLL */
为了解决在Debug模式下调试报错的问题,需在C++程序头部进行如下引用:
#ifdef _DEBUG
#undef _DEBUG
#include "Python.h"
#define _DEBUG
#else
#include "Python.h"
#endif
C++调用Python用法示例
1)执行简单Python语句
int main()
{
Py_Initialize();
PyRun_SimpleString("print('Hello Python!')\n");
Py_Finalize();
return 0
}
2)调用python文件中的函数(无参数)
Python代码:Test001.py
def Hello():
print("Hello Python hello python ")
C++代码
void mian()
{
Py_Initialize();//调用Py_Initialize()进行初始化
if (!Py_IsInitialized())
{
printf("初始化失败!");
}
PyRun_SimpleString("import os,sys");
PyRun_SimpleString("sys.path.append('./')");//这一步很重要,修改Python路径
PyObject * pModule = NULL;
PyObject * pFunc = NULL;
pModule = PyImport_ImportModule("Test001");//调用的Python文件名,将Test001.py文件放在
pFunc = PyObject_GetAttrString(pModule, "Hello");//调用的函数名
PyEval_CallObject(pFunc, NULL);//调用函数,NULL表示参数为空
//PyObject_CallObject(pFunc, NULL);
if (pFunc)
Py_DECREF(pFunc);//此步为对Python传过来的对象引用次数逐步降低
if (pModule)
Py_DECREF(pModule);
Py_Finalize();//调用Py_Finalize,和Py_Initialize相对应的.
}
3)调用Python文件中的函数,输入多个参数并获取单个返回值
Python代码:Test001.py
def Hello():
print("Hello Python hello python ")
def Add(a,b):
return a+b
C++代码:
void main()
{
Py_Initialize();
if (!Py_IsInitialized())
{
printf("初始化失败!");
}
PyRun_SimpleString("import os,sys");
PyRun_SimpleString("sys.path.append('./')");//这一步很重要,修改Python路径
int res;
PyObject *pModule = NULL;
PyObject *pFunc = NULL;
PyObject *pArgs = NULL;
PyObject *pRet = NULL;
/* import */
pModule = PyImport_ImportModule("Test001");//调用的Python文件名
if (!pModule)
{
printf("import python failed!!\n");
}
/* Test001.Add */
pFunc = PyObject_GetAttrString(pModule, "Add");
if (!pFunc)
{
printf("get python function failed!!!\n");
}
/* build args */
pArgs = PyTuple_New(2);
PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", a));
PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", b));
/* call */
pRet = PyEval_CallObject(pFunc, pArgs);
PyArg_Parse(pRet, "i", &res);//i表示转换成int型变量
return res;
if(pRet)
Py_DECREF(pRet);
if (pArgs)
Py_DECREF(pArgs);
if (pFunc)
Py_DECREF(pFunc);
if (pModule)
Py_DECREF(pModule);
Py_Finalize();
}
4)调用Python文件中的函数,输入多个参数并获取单个返回值
Python代码:Test001.py
def Hello():
print("Hello Python hello python ")
def Add(a,b):
return a+b
def AddMult(a,b):
return a+b,a*b
C++代码:
void main()
{
Py_Initialize();
PyRun_SimpleString("import os,sys");
PyRun_SimpleString("sys.path.append('./')");//这一步很重要,修改Python路径
PyObject *pModule = NULL;
PyObject *pFunc = NULL;
PyObject *pArgs = NULL;
PyObject *pRet = NULL;
/* import */
pModule = PyImport_ImportModule("Test001");
if (!pModule)
{
printf("import python failed!!\n");
}
//Test001.AddMult
pFunc = PyObject_GetAttrString(pModule, "AddMult");
if (!pFunc)
{
printf("get python function failed!!!\n");
}
/* build args */
//pArgs = Py_BuildValue("ii", a, b);
pArgs = PyTuple_New(2);
PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", a));
PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", b));
/* call */
//pRet = PyObject_CallObject(pFunc, pArgs);
pRet = PyEval_CallObject(pFunc, pArgs);
int c = 0;
int d = 0;
PyArg_ParseTuple(pRet, "ii", &c, &d);
std::cout<<"sum:"<< c <<std::endl;
std::cout<<"mult:"<< d <<std::endl;
if (pRet)
Py_DECREF(pRet);
if (pArgs)
Py_DECREF(pArgs);
if (pFunc)
Py_DECREF(pFunc);
if (pModule)
Py_DECREF(pModule);
//只有最后一步才调用Py_Finalize(),此时python全局变量一直保存着
Py_Finalize();
}
5)执行Python文件,并传入系统参数
Python代码:
import sys,os
print(sys.argv[0])
C++代码:
void main()
{
//第一步:初始化Python
//在调用Python的提供的给C的API之前,通过执行初始化
//来添加Python的内建模块、__main__、sys等
Py_Initialize();
//检查初始化是否完成
if (!Py_IsInitialized())
{
printf("初始化失败!");
}
//第二步:导入sys模块
PyRun_SimpleString("import os,sys");
PyRun_SimpleString("sys.path.append('./')");//这一步很重要,修改Python路径
//第三步:导入执行脚本时的命令行参数,如:./sample.py arg1 arg2
int argc = 1;
char* argv[1];
argv[0] = (char*)"This is a test string";
PySys_SetArgv(argc, argv);
//第四步:执行调用脚本文件命令,注意文件的路径
PyObject* PyFileObject = PyFile_FromString((char*)"Test002.py", (char*)"rb");
PyRun_SimpleFile(PyFile_AsFile(PyFileObject), (char*)"Test002.py");
//第五步:关闭Python解释器
Py_Finalize();
}
6)将Python文件以字符串的形式调用
C++代码:
void main()
{
Py_Initialize();
//检查初始化是否完成
if (!Py_IsInitialized())
{
printf("初始化失败!");
}
//第二步:导入sys模块
PyRun_SimpleString("import os,sys");
PyRun_SimpleString("sys.path.append('./')");//这一步很重要,修改Python路径
//第三步:导入执行脚本时的命令行参数,如:./sample.py arg1 arg2
int argc = 1;
char* argv[1];
argv[0] = (char*)"BW.txt";
PySys_SetArgv(argc, argv);
//将下面的python语句转化为16进制形式
//
//import sys
//
// def main() :
// print(sys.argv[0])
//
//
// if __name__ == '__main__' :
// main()
unsigned char arg2[] = {
0x0D, 0x0A, 0x69, 0x6D, 0x70, 0x6F, 0x72, 0x74, 0x20, 0x73, 0x79, 0x73, 0x0D, 0x0A, 0x0D, 0x0A,
0x64, 0x65, 0x66, 0x20, 0x6D, 0x61, 0x69, 0x6E, 0x28, 0x29, 0x3A, 0x0D, 0x0A, 0x09, 0x70, 0x72,
0x69, 0x6E, 0x74, 0x28, 0x73, 0x79, 0x73, 0x2E, 0x61, 0x72, 0x67, 0x76, 0x5B, 0x30, 0x5D, 0x29,
0x0D, 0x0A, 0x0D, 0x0A, 0x0D, 0x0A, 0x69, 0x66, 0x20, 0x5F, 0x5F, 0x6E, 0x61, 0x6D, 0x65, 0x5F,
0x5F, 0x3D, 0x3D, 0x27, 0x5F, 0x5F, 0x6D, 0x61, 0x69, 0x6E, 0x5F, 0x5F, 0x27, 0x3A, 0x0D, 0x0A,
0x09, 0x6D, 0x61, 0x69, 0x6E, 0x28, 0x29, 0x00
};
Py_Finalize();
}
7)定义Python 函数,生成PythonModule,并调用PythonModule
C++代码:
void main()
{
Py_Initialize();
// compile our function
std::stringstream buf;
buf << "def add( n1 , n2 ) :" << std::endl
<< " return n1+n2" << std::endl;
PyObject* pCompiledFn = Py_CompileString(buf.str().c_str(), "", Py_file_input);//将Python 指令进行编译
assert(pCompiledFn != NULL);
// create a module
PyObject* pModule = PyImport_ExecCodeModule((char*)"test", pCompiledFn);//将编译后的Python指令生成为Python Module
assert(pModule != NULL);
// locate the "add" function (it's an attribute of the module)
PyObject* pAddFn = PyObject_GetAttrString(pModule, "add");//调用Python Module中的add函数
assert(pAddFn != NULL);
int a = 1;
int b = 2;
PyObject* pArgs = PyTuple_New(2);//创建参数元组
PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", a));
PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", b));
//PyObject* pRet = PyObject_CallObject(pAddFn, pArgs);//调用Python Module中add函数
int res;
PyArg_Parse(pRet, "i", &res);//将返回的结果转化为int类型
std::cout << res << std::endl;
// clean up
Py_DecRef(pAddFn);
Py_DecRef(pModule);
Py_DecRef(pCompiledFn);
Py_Finalize();
}
8)调用Pyhton中的类、实例、函数,参考下面的链接
[C++/Python] 如何在C++中使用一个Python类?
参考文献
C++调用python的那些坑(详细教程步骤)
Calling Python code from your program
C++调用Python浅析