1. 程式人生 > >C++和python混合程式設計之在python類建構函式中傳參方法

C++和python混合程式設計之在python類建構函式中傳參方法

一、說明: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,如有錯誤歡迎指正。