Python Embedding 开发 - 函数调用
    前面两节的helloworld 程序都是很简单的应用,对于一些复杂的情况下,比如我们要调用摸个python模块中的某个指定的函数,获取其返回结果并显示结果。或者我们需要在调用Python 中的函数的时候传入函数参数供脚本处理等等操作的话,简单的helloworld 是不能满足我们的需求的。还是先来看下面的例子程序中是如何做到的吧。
有python脚本文件functioncall.py,其内容如下:
view plaincopy to clipboardprint?
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
1. def getMsg(): 
2.     return {1:2, 1.2:('a',),"key":[1,2,3]} 
3.      
4. if __name__ == "__main__": 
5.     print getMsg()
我们希望能够调用getMsg函数,并在C++代码中获取到其返回值,示例代码如下:
view plaincopy to clipboardprint?
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
1. #include <Python.h>   
2. #include <iostream>   
3. void printUsage() 
4.
5.     std::cerr << " ModuleName funcName" << std::endl; 
6.
7. /************************************************************************/ 
8. /* Python 解释器的初始化与析构的封装,简化使用                          */ 
9. /************************************************************************/ 
10. class PyInterpreter 
11.
12. public: 
13.     PyInterpreter(const char* strPyHome) 
14.     {   
15.         Py_SetPythonHome((char*)strPyHome); 
16.         Py_Initialize(); 
17.         if (!Py_IsInitialized()) 
18.         { 
19.             std::cerr << "Python initialize fail" << std::endl; 
20.         } 
21.     } 
22.     ~PyInterpreter() 
23.     { 
24.         Py_Finalize(); 
25.     } 
26.     operator void*() 
字符串函数怎么获取
27.     { 
28.         return Py_IsInitialized()? this:NULL; 
29.     } 
30. }; 
31. /************************************************************************ 
32.  PyObject* 的简易封装,注意在出作用域时就会减引用,这样代码中看起来清爽点, 
33.  不然到处都是减引用的宏调用。 
34. /************************************************************************/ 
35. class PythonObject 
36.
37. public: 
38.     PythonObject(PyObject* ptr):m_ptr(ptr){} 
39.     ~PythonObject() 
40.     { 
41.         Py_XDECREF(m_ptr); 
42.     } 
43.     operator PyObject*() 
44.     { 
45.         return m_ptr; 
46.     } 
47. private: 
48.     PyObject* m_ptr; 
49. }; 
50. int main(int argc, char* argv[]) 
51.
52.     if (argc != 3) 
53.     { 
54.         printUsage(); 
55.         return 0; 
56.     } 
57.     /************************************************************************/ 
58.     /* 创建全局解释器                                                       */ 
59.     /************************************************************************/ 
60.     PyInterpreter interpreter("D://myprogram//python2.6//released"); 
61.     const char* strFileName = argv[1]; 
62.     const char* strFuncName = argv[2]; 
63.     /************************************************************************/ 
64.     /* import 模块                                                          */ 
65.     /************************************************************************/ 
66.     PythonObject pModule(PyImport_ImportModule(strFileName)); 
67.     if (!pModule) 
68.     { 
69.         std::cerr << "import module fail: " << strFileName << std::endl; 
70.         return 0; 
71.     } 
72.     /************************************************************************/ 
73.     /* 获取模块中的函数对象                                                 */ 
74.     /************************************************************************/ 
75.     PythonObject pFunc(PyObject_GetAttrString(pModule, strFuncName)); 
76.     if ((!pFunc) ||!PyCallable_Check(pFunc)) 
77.     { 
78.         std::cerr << "cannot find function :" << strFuncName << ", in module:" << strFileName << std::endl; 
79.         return 0; 
80.     } 
81.     // 创建函数参数列表,注意,即使没有参数的,也好构造个0长的tuple对象传入   
82.     PythonObject pArgs(PyTuple_New(0)); 
83.     // 调用函数   
84.     PythonObject result(PyObject_CallObject(pFunc, pArgs)); 
85.     if (!result) 
86.     { 
87.         std::cerr << "call func fail, funcname:" << strFuncName << std::endl; 
88.     } 
89.     // 将函数的返回值以字符串形式打印屏幕   
90.     PythonObject resultString(PyObject_Repr(result)); 
91.     std::cout << "result is: " << PyString_AsString(resultString) << std::endl; 
92.     return 0; 
93.  
    看完上面的代码后,是不是觉得和前面的例子程序不一样了,呵呵,前面的hello world过于简单,这里以及以后的例子等比较复杂,所以将一些共性的东西抽象成c++的类来使用,方便使用。
    类PyInterpreter 封装了Python的全局解释器的创建和销毁。
    类PythonObject 封装了PyObject* 的减引用操作,不让代码显得罗嗦。
    将代码编译好后,运行命令行 functioncall getMsg,输入内容为:
result is: {1: 2, 1.2: ('a',), 'key': [1, 2, 3]}
看到结果了,我们再回过头来看看要完成这个功能需要哪些知识点:
1、PyImport_ImportModule 函数,这个函数相当于python脚本中的import 关键字,已在导入模块至全局解释器(其实这个说话是不正确的,在某些情况下,其实不是导入到全局解释器中,关于这点后续会介绍,这里大家可以认为是加到了全局解释器中),这个函数返回一个Python 对象,指向导入的模块对象,下面将使用这个对象进行操作。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。