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小时内删除。
发表评论