C++和python混合编程之在python类构造函数中传参方法

版权声明:本文为博主原创文章,转载请注明出处。作者:ISmileLi 博客地址:http://blog.csdn.net/toby54king。 https://blog.csdn.net/toby54king/article/details/84501283

一、说明:C++项目中用到python相关的知识,这两天研究了一下C++与python的混合编程,网上有很多这方面的介绍,但是怎么使用python类的构造函数中传参的介绍却没有,这里研究一下,分享出来。(C++和python相互调用的相关接口查询https://docs.python.org/2/index.html)

二、测试代码
1、C++代码:

/*=================CplusUsePython.h====================*/
#ifndef CPLUSUSEPYTHON_H
#define CPLUSUSEPYTHON_H
#include <Python.h>
#include <string>
using namespace std;

class CplusUsePython
{
public:
    CplusUsePython();
    ~CplusUsePython();

    static CplusUsePython* instance()
    {
        static CplusUsePython instance;
        return &instance;
    }

    // 初始化相关操作
    int init(const string pyFilePath, const string pyFileNameNoSuffix);
    // C++调用python函数
    int CCallFunction(const string pyFuncName, const string message);
    // C++调用python类中的函数
    int CCallClassFunc(const string pyFuncName, const string name, const int age);

private:
    PyObject *pName;
    PyObject *pModule;
    PyObject *pFunc;
    PyObject *pArgs;
    PyObject *pClass;
    PyObject *pInstance;
};

#endif // CPLUSUSEPYTHON_H

/*=================CplusUsePython.cp====================*/
#include "CplusUsePython.h"
#include <sstream>

CplusUsePython::CplusUsePython()
{

}

CplusUsePython::~CplusUsePython()
{
    if (Py_IsInitialized()) {
        if (pName) Py_DECREF(pName);
        if (pArgs) Py_DECREF(pArgs);
        if (pModule) Py_DECREF(pModule);
        if (pFunc) Py_DECREF(pFunc);
        if (pClass) Py_DECREF(pClass);
        if (pInstance) Py_DECREF(pInstance);
        Py_Finalize();
    }
}

//************************************
// 函数名称: init
// 函数说明:初始化相关操作
// 返 回 值: int
// 参    数: const string pyFilePath
// 参    数: const string pyFileNameNoSuffix
// 作    者:ISmileLi
// 作成日期:2018/11/25
// 修改记录:
//************************************
int CplusUsePython::init(const string pyFilePath, const string pyFileNameNoSuffix)
{
    int ret = 0;
    if (pyFilePath.empty() || pyFileNameNoSuffix.empty())
        return -1;
    Py_Initialize();
    pName = NULL;
    pModule = NULL;
    pFunc = NULL;
    pArgs = NULL;
    pClass = NULL;
    pInstance = NULL;
    // 判断初始化是否成功
    if (!Py_IsInitialized())
        return -2;
    // 调用python中需要使用的模块
    ret = PyRun_SimpleString("import sys");
    if (ret != 0)
    {
        // 导入失败,关闭python调用
        Py_Finalize();
        return -3;
    }
    // 导入python文件的相关操作
    if (ret == 0)
    {
        stringstream strpycmd;
         strpycmd << "sys.path.append('" << pyFilePath << "')";
        ret = PyRun_SimpleString(strpycmd.str().c_str());
    }
    if (ret != 0)
    {
        Py_Finalize();
        return -4;
    }
    pName = PyString_FromString(pyFileNameNoSuffix.c_str());
    if ((pModule = PyImport_Import(pName)) == NULL || pName == NULL)
    {
        Py_Finalize();
        return -5;
    }
    return 0;
}

//************************************
// 函数名称: CCallFunction
// 函数说明:C++调用python中的函数
// 返 回 值: int
// 参    数: const string pyFuncName
// 参    数: const string message
// 作    者:ISmileLi
// 作成日期:2018/11/25
// 修改记录:
//************************************
int CplusUsePython::CCallFunction(const string pyFuncName,const string message)
{
    if (pyFuncName.empty() || message.empty())
    {
        return -1;
    }

    pFunc = PyObject_GetAttrString(pModule, pyFuncName.c_str());
    if(!pFunc)
    {
        return -2;
    }
    // 调用python函数,s表示传入参数是字符串类型
    PyObject *pRet = PyObject_CallFunction(pFunc, "s", (char*)message.c_str());
    if(pRet)
    {
        Py_DECREF(pRet);
    }
    else
    {
        return -3;
    }

    return 0;
}

//************************************
// 函数名称: CCallClassFunc
// 函数说明:C++调用python类中的函数
// 返 回 值: int
// 参    数: const string pyFuncName
// 参    数: const string name
// 参    数: const string age
// 作    者:ISmileLi
// 作成日期:2018/11/25
// 修改记录:
//************************************
int CplusUsePython::CCallClassFunc(const string pyFuncName,const string name, const int age)
{
    if (pyFuncName.empty() || name.empty() || age <= 0)
    {
        return -1;
    }


    // 向Python传参数是以元组(tuple)的方式传递的
    pArgs = PyTuple_New(2);
    //  PyObject* Py_BuildValue(char *format, ...) 将C++的变量转换成一个Python对象
    //  s 表示字符串,i 表示整型变量,f 表示浮点数
    PyTuple_SetItem(pArgs, 0, Py_BuildValue("s", name.c_str()));
    PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", age));

    // 增加支持调用类中方法的操作
    pClass = PyObject_GetAttrString(pModule,"ISmileLi"); // DrawPic为类的名字
    if(!pClass)
    {
        return -2;
    }

    // 传入python构造函数中的两个参数
    pInstance = PyInstance_New(pClass,pArgs,NULL);
    if(!pInstance)
    {
        return -3;
    }
    // 调用类中的函数
    pFunc = PyObject_CallMethod(pInstance,(char*)pyFuncName.c_str(),NULL,NULL);
    if(!pFunc)
    {
        return -4;
    }

    return 0;
}
/*=================main.c================*/
#include <Python.h>
#include <iostream>
#include <string>
#include "CplusUsePython.h"

using namespace std;

int main ()
{
    // C++和python相互调用的相关接口查询https://docs.python.org/2/index.html
    string pyFilePath = "/work/test/testC++/test_C_use_Python";
    int ret = CplusUsePython::instance()->init(pyFilePath,"ISmileLi");
    if(ret != 0)
    {
        cout << "init failure!" << endl;
    }
    ret = CplusUsePython::instance()->CCallFunction("print_message","this is test C++ use python!");

    ret = CplusUsePython::instance()->CCallClassFunc("print_name","LiSa",18);
    ret = CplusUsePython::instance()->CCallClassFunc("print_age","LiSa",18);
    ret = CplusUsePython::instance()->CCallClassFunc("print_name_age","LiSa",18);

    return 0;
}

2、python代码

#filename: ISmileLi.py
# -*- coding: utf-8 -*-
class ISmileLi:
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def print_name(self):
        print("===in function print_name===")
        print("name:",self.name)

    def print_age(self):
        print("===in function print_age===")
        print("age:",self.age)

    def print_name_age(self):
        print("===in function print_name_age===")
        print("name:%s age:%d" % (self.name,self.age))


def print_message(message):
    print("===in function print_message===")
    print("message:",message)

三、运行结果
在这里插入图片描述

说明:由于我也不擅长python,如有错误欢迎指正。

猜你喜欢

转载自blog.csdn.net/toby54king/article/details/84501283