Python Embedding 开发 - 函数调用 (一)

来源:互联网 发布:2017青少年编程大赛 编辑:程序博客网 时间:2024/05/10 00:01

前面两节的helloworld 程序都是很简单的应用,对于一些复杂的情况下,比如我们要调用摸个python模块中的某个指定的函数,获取其返回结果并显示结果。或者我们需要在调用Python 中的函数的时候传入函数参数供脚本处理等等操作的话,简单的helloworld 是不能满足我们的需求的。还是先来看下面的例子程序中是如何做到的吧。

 

有python脚本文件functioncall.py,其内容如下:

 

我们希望能够调用getMsg函数,并在C++代码中获取到其返回值,示例代码如下:

 

看完上面的代码后,是不是觉得和前面的例子程序不一样了,呵呵,前面的hello world过于简单,这里以及以后的例子等比较复杂,所以将一些共性的东西抽象成c++的类来使用,方便使用。

 

类PyInterpreter 封装了Python的全局解释器的创建和销毁。

 

类PythonObject 封装了PyObject* 的减引用操作,不让代码显得罗嗦。

 

将代码编译好后,运行命令行pyEmbed.exe functioncall getMsg,输入内容为:

result is: {1: 2, 1.2: ('a',), 'key': [1, 2, 3]}

 

 

看到结果了,我们再回过头来看看要完成这个功能需要哪些知识点:

1、PyImport_ImportModule 函数,这个函数相当于python脚本中的import 关键字,已在导入模块至全局解释器(其实这个说话是不正确的,在某些情况下,其实不是导入到全局解释器中,关于这点后续会介绍,这里大家可以认为是加到了全局解释器中),这个函数返回一个Python 对象,指向导入的模块对象,下面将使用这个对象进行操作。

   我们知道在Python脚本中如果需要使用另外一个module中方法以及数据的时候,大家都会用类似下面的方式来使用。

 

import 关键字的作用就是将foo模块导入到python解释器中,在使用其中的函数时使用foo.bar来调用bar这个函数。

 

相同的道理,在C++中如果需要调用functioncall.py脚本的函数getMsg,那么就要先到functioncall 这个模块导入到解释器中去,上面的函数PyImport_ImportModule 就是做这个事情的。那么这个函数到底是怎么将functioncall模块加载起来的呢?

 

在python脚本中,当我们需要import一个自定义的模块时,如果需要加载的模块在当前目录下,可以直接import,但是当模块在另外一个目录下时,通常的做法是将这个模块所在的path加到 sys.path这个list中去,然后再import 模块。

其实在C++嵌入Python的使用中也有类似的需求,先使用Python API PySys_GetObject("path") 获取到sys.path对应的PyObject对象指针,再将路径插入到这个list对象中。

 

2、PyObject_GetAttrString 函数,这个函数的作用是获取Python对象中的指定名称的Python对象,在这个例子中,脚本functioncall.py中的函数getMsg就是模块functioncall中一个函数对象,所以我们可以使用这个函数来获取functioncall模块的函数getMsg对应的Python对象。

3、PyCallable_Check 函数,顾名思义,检查python对象是否为可调用,函数为可调用对象。

4、PyTuple_New 函数,在C++代码中构建一个tuple对象。

5、PyObject_CallObject 函数,这个函数就是我们这个样例的核心函数,其第一个参数为可调用对象,第二个参数为调用第一个参数所需要的参数tuple对象,Python将会在该函数中完成对getMsg函数的调用过程,并返回getMsg函数的返回数据。

6、PyObject_Repr 函数,将python对象转换为字符形式。相当于python中的str函数。

 

呵呵,有了这些作为基础,写个将“hello world”作为函数参数传入到某个python脚本中的函数中并且打印输出应该不是难事。请感兴趣的考虑考虑!

 

原创粉丝点击