Linux下简单的c++调用python例子

1.环境问题:

在linux一般自带python解释器,我的为python 2.7.5.(可根据python --version查看)。写环境验证代码,写简单的c++代码,引入头文件#include,进行编译。可能出现如下错误:

Linux下简单的c++调用python例子_第1张图片

采用yum install python-devel.x86_64 命令解决,编译没有报错可以忽略。

 

2.使用步骤(实例)

1.新建python文件和c++文件

 

2.编写想用python模块完成的代码,例如:

Linux下简单的c++调用python例子_第2张图片

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 进行编译

Linux下简单的c++调用python例子_第3张图片

 

可以把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点。

 Linux下简单的c++调用python例子_第4张图片

 

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

 

结果如下:

Linux下简单的c++调用python例子_第5张图片

 

针对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

你可能感兴趣的:(C++)