C调用python
1:调用Python中的类#include <python3.6m/Python.h>int main(int argc,char **argv){PyObject *pModule, *pDict, *pFRCNN, *pFrcnn;PyObject *result, *result1;//初始化pythonPy_Initialize();if (!Py_IsInitialized(
一:调用流程
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=%s\n", 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=%d\n", 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-%d\n", name, age);
PyArg_ParseTuple(result1, "si", &name, &age);
printf("result1:%s-%d\n", 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
#include <python3.6m/Python.h>
int 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=%s\n", 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=%d\n", 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-%d\n", name, age);
PyArg_ParseTuple(result1, "si", &name, &age);
printf("result1:%s-%d\n", 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 = %s\n", name);
PyObject_CallMethod(pInstance, "setInfo", "(Osi)", pInstance, "mandy",20);
如果把sayHello里边的 self.name = "ssss" 注释打开 在运行 就会是如下结果了
昨天测试的时候还报了 instancemethod 没有 name 属性
具体为啥后边研究了再补上
附上:c++访问python3-实例化类的方法
更多推荐
所有评论(0)