1.环境问题:
在linux一般自带python解释器,我的为python 2.7.5.(可根据python --version查看)。写环境验证代码,写简单的c++代码,引入头文件#include
采用yum install python-devel.x86_64 命令解决,编译没有报错可以忽略。
2.使用步骤(实例)
1.新建python文件和c++文件
2.编写想用python模块完成的代码,例如:
class Student:
def SetName(self,name):
self._name = name
def PrintName(self):
print self._name
def hello():
print "Hello World\n"
def world(name):
print "name"
实现了一个学生类,实现了set函数,一个对象set完之后可以答应出成员的信息。后面的两个函数单为简的测试函数。
3.编写c++代码,例如:
#include
#include
#include
int main () {
//使用python之前,要调用Py_Initialize();这个函数进行初始化
Py_Initialize();
//导入环境变量
PyRun_SimpleString("import sys");
//python脚本路径
PyRun_SimpleString("sys.path.append('./')"); //放在cpp的同一路径下
PyObject * pModule = NULL;
PyObject * pFunc = NULL;
PyObject * pClass = NULL;
PyObject * pInstance = NULL;
// PyImport_ImportModule函数载入python脚本,参数为为python脚本名称,因为是//模块化的导入,所以当代码处于运行期的时候就会生成一个.pyc文件,这样的话和直//接使用.pyc文件有同样的效果,下面做了两种方式运行效率的比较
pModule = PyImport_ImportModule("nounpy");
//这里是要调用的函数名
pFunc= PyObject_GetAttrString(pModule, "hello");
//调用函数
PyEval_CallObject(pFunc, NULL);
Py_DECREF(pFunc);
//测试调用python的类
pClass = PyObject_GetAttrString(pModule, "Student");
if (!pClass) {
printf("Can't find Student class.\n");
return -1;
}
pInstance = PyInstance_New(pClass, NULL, NULL);
if (!pInstance) {
printf("Can't create Student instance.\n");
return -1;
}
//调用其中的类方法
PyObject_CallMethod(pInstance, "SetName", "(s)","I am c++ args");
PyObject_CallMethod(pInstance, "PrintName",NULL,NULL);
//调用Py_Finalize,这个根Py_Initialize相对应的。
Py_Finalize();
return 0;
}
加粗函数为c++提供的专门操作python对象的函数。
使用g++ -o noun noun.cpp -lpython2.7 进行编译
可以把c++调用python步骤总结如下:
分别为:1.进行python的初始化工作(表示要执行python脚本等工作);2.声明需要的PyObject*类型的指针变量;3.采用PyImport_ImportModule导入模块,参数为python脚本名称(因为有的时候 python解释器是不会生成.pyc文件的),如果名称不对会导入失败,函数返回为空;4.然后通过PyObject_GetAttrString函数获取类型或者函数,如果成功,返回python*类型的指针(有点类似与调用dll的GetProcAddress,获取到了函数或者类型的地址);5.如果是直接要调用的是函数,采用PyEval_CallObject、Py_DECREF进行调用,如果是类,需要先调用PyInstance_New函数,然后再通过PyObject_CallMethod函数执行类方法。
可以分为对单个函数的使用和对类的使用,两种场景采用不同的步骤和方法,主要区别于上述的 第5点。
3.直接使用.py和提前编译好.pyc使用效率比较
运行效率的比较,python实现了一个五百万次的循环:
1.使用.pyc文件的方式(对python的源码文件进行模块化编译,例如python -m py_compile nounpy.py,将生成的nounpy.pyc拷贝到如下目录,进行如下图使用)
g++ -o noun noun.cpp -lpython2.7
./noun
结果如下:
2.使用.py文件的方式:
g++ -o noun noun.cpp -lpython2.7
./noun
结果如下:
针对python代码不大的调用,可以看出,提前编译好.pyc使用和直接使用.py区别不是很大(耗时基本相同)。每一次把脚本模块导入的时候会检测相应路径下是否有相应的.pyc,如果没有会生成,如果有就直接快速加载。因为python代码少,解释出来耗时很短,所以这两种使用方式最终耗时也基本一样。不过建议先编译好代码,生成.pyc供c++使用,这样的话可以做到隐藏源代码并且需要的功能也可以持久化保存。
4.一些关键函数(c++提供给操作python对象的)
初始化
Py_Initialize
PyRun_SimpleString
PyRun_SimpleString
加载脚本
PyImport_ImportModule
函数的使用
PyObject_GetAttrString
PyEval_CallObject
Py_DECREF
类的使用
PyObject_GetAttrString
PyInstance_New
PyObject_CallMethod
结束
Py_Finalize