一:调用流程
1:必须首先调用Py_Initialize(),初始化python运行所需模块。
2:接着调用Py_IsInitialized(),检查初始化是否成功
3:调用PyRun_SimpleString(),引入常用的路径
4:调用Pyimport_importModule(),加载python模块,引入py文件
5:调用PyModule_GetDict(),获取模块字典
6:调用PyObject_GetAttrString() PyDict_GetItemString(),获取相应的方法或者类
7:调用Pyeval_CallObject() PyObject_CallMethod() 调用相应的方法
8:调用Py_DECREF() 释放python api创建的对象
9:调用Py_Finalize() 释放python模块
二:实例
1:调用py文件中的普通方法
Py_Initialize(); if (!Py_IsInitialized()) { printf("python初始化失败!"); return 0; } PyRun_SimpleString("import sys"); PyRun_SimpleString("sys.path.append('./')"); pModule = Pyimport_importModule("test_cpp_call_py"); assert(pModule != NULL); PyObject *pFuncHello = PyObject_GetAttrString(pModule, "Hello"); PyObject *pArgHello = Py_BuildValue("(s)", "Hello Charity"); PyObject *resultHello = Pyeval_CallObject(pFuncHello, pArgHello); char *hello = NULL; PyArg_Parse(resultHello,"s",&hello); printf("call Hello result=%sn", hello); pDict = PyModule_GetDict(pModule); assert(pDict != NULL); PyObject* pFuncAdd = PyDict_GetItemString(pDict, "Add"); PyObject* pArgAdd = Py_BuildValue("(i, i)", 1, 2); PyObject *resultAdd = Pyeval_CallObject(pFuncAdd, pArgAdd); int c; PyArg_Parse(resultAdd, "i", &c); printf("call Add result=%dn", c);
上边代码展示了2种获取方法,一种是直接从pModule中通过PyObject_GetAttrString()根据方法名获取方法,另外一种是先从pModule中通过调用PyModule_GetDict获取pDict,然后在从pDict中通过调用PyDict_GetItemString(),同样是根据方法名获取方法。
2:调用py文件中的类,先获取类 再创建类对象
pClass = PyDict_GetItemString(pDict, "Person"); assert(pClass != NULL); pInstance = PyObject_CallObject(pClass, NULL); assert(pInstance != NULL);
pClass 就是类型从dic中获取的类,然后需要实例化才能调用实例方法
result = PyObject_CallMethod(pInstance, "getInfo", ""); PyObject_CallMethod(pInstance, "setInfo", "si", "tyl", 24); result1 = PyObject_CallMethod(pInstance, "getInfo", ""); PyArg_ParseTuple(result, "si", &name, &age); printf("result:%s-%dn", name, age); PyArg_ParseTuple(result1, "si", &name, &age); printf("result1:%s-%dn", name, age);
3:释放资源
Py_DECREF(pModule); Py_DECREF(pDict); Py_DECREF(pClass); Py_DECREF(pInstance); Py_DECREF(result); Py_Finalize();
三:编译+测试
test_cpp_call_py.c
#includeint main(int argc,char **argv) { PyObject *pModule, *pDict, *pClass, *pInstance; PyObject *result, *result1; //初始化python Py_Initialize(); if (!Py_IsInitialized()) { printf("python初始化失败!"); return 0; } PyRun_SimpleString("import sys"); PyRun_SimpleString("sys.path.append('./')"); pModule = Pyimport_importModule("test_cpp_call_py"); assert(pModule != NULL); PyObject *pFuncHello = PyObject_GetAttrString(pModule, "Hello"); PyObject *pArgHello = Py_BuildValue("(s)", "Hello Charity"); PyObject *resultHello = Pyeval_CallObject(pFuncHello, pArgHello); char *hello = NULL; PyArg_Parse(resultHello,"s",&hello); printf("call Hello result=%sn", hello); Py_DECREF(pFuncHello); Py_DECREF(pArgHello); Py_DECREF(resultHello); pDict = PyModule_GetDict(pModule); assert(pDict != NULL); PyObject* pFuncAdd = PyDict_GetItemString(pDict, "Add"); PyObject* pArgAdd = Py_BuildValue("(i, i)", 1, 2); PyObject *resultAdd = Pyeval_CallObject(pFuncAdd, pArgAdd); int c; PyArg_Parse(resultAdd, "i", &c); printf("call Add result=%dn", c); Py_DECREF(pFuncAdd); Py_DECREF(pArgAdd); Py_DECREF(resultAdd); //通过字典属性获取模块中的类 pClass = PyDict_GetItemString(pDict, "Person"); assert(pClass != NULL); pInstance = PyObject_CallObject(pClass, NULL); assert(pInstance != NULL); PyRun_SimpleString("print('-'*10, 'Python start', '-'*10)"); result = PyObject_CallMethod(pInstance, "getInfo", ""); PyObject_CallMethod(pInstance, "setInfo", "si", "tyl", 24); result1 = PyObject_CallMethod(pInstance, "getInfo", ""); char* name; int age; PyArg_ParseTuple(result, "si", &name, &age); printf("result:%s-%dn", name, age); PyArg_ParseTuple(result1, "si", &name, &age); printf("result1:%s-%dn", name, age); PyRun_SimpleString("print('-'*10, 'Python end', '-'*10)"); Py_DECREF(result); Py_DECREF(result1); Py_DECREF(pModule); Py_DECREF(pDict); Py_DECREF(pClass); Py_DECREF(pInstance); PyRun_SimpleString("print('-'*10, 'decref end', '-'*10)"); Py_Finalize(); }
test_cpp_call_py.py
#coding:utf-8 ''' create on 2017-04-20 @author:sandy ''' def Hello(s): print ("Hello World") print(s) return s def Add(a, b): print('a=', a) print ('b=', b) return a + b class Person(object): def __init__(self): self.name = "mandy" self.age = 20 def setInfo(self,name,age): print(self,dir(self),name) self.name = name self.age = age def getInfo(self): print('python: name={}, age={}'.format(self.name, self.age)) return self.name, self.age def sayHello(self, name): print(self,dir(self),name) # self.name = "sssss" print ("Hello,", name) return name
由于本地有多个版本的Python,所以要指定python3.6m
gcc test_cpp_call_py.c -o nonu -lpython3.6m
另外:
看文档还有一种方法创建,但是这个pInstance 和 上边方式创建的pInstance 是不一样的,具体怎么一个不一样,我还没有研究透。。。
pInstance = PyInstanceMethod_New(pClass); result = PyObject_CallMethod(pInstance, "sayHello", "(Os)", pInstance, "Charity"); char* name=NULL; PyArg_Parse(result, "s", &name); printf("call sayHello = %sn", name); PyObject_CallMethod(pInstance, "setInfo", "(Osi)", pInstance, "mandy",20);
如果把sayHello里边的 self.name = "ssss" 注释打开 在运行 就会是如下结果了
昨天测试的时候还报了 instancemethod 没有 name 属性
具体为啥后边研究了再补上
附上:c++访问python3-实例化类的方法c++访问python3-实例化类的方法_love_clc的专栏-CSDN博客
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)