C调用python

C调用python,第1张

C调用python

一:调用流程

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

#include 
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=%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博客

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5635777.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存