程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 淺析 C++ 調用 Python 模塊

淺析 C++ 調用 Python 模塊

編輯:關於C++

淺析 C++ 調用 Python 模塊

作為一種膠水語言,Python 能夠很容易地調用 CC++ 等語言,也能夠通過其他語言調用 Python 的模塊。

Python 提供了 C++ 庫,使得開發者能很方便地從 C++ 程序中調用 Python 模塊。

具體的文檔參考官方指南:
Embedding Python in Another Application

調用方法

1 鏈接到 Python 調用庫

Python 安裝目錄下已經包含頭文件( include 目錄)和庫文件 ( Windows 下為 python27.lib)。

使用之前需要鏈接到此庫。

2 直接調用 Python 語句

#include "python/Python.h"

int main()
{
    Py_Initialize();    ## 初始化

    PyRun_SimpleString("print 'hello'");

    Py_Finalize();      ## 釋放資源
}

3 加載 Python 模塊並調用函數

~/test 目錄下含有 test.py :

def test_add(a, b):
    print 'add ', a, ' and ', b
    return a+b

則可以通過以下代碼調用 test_add 函數 :

#include "python/Python.h"
#include 
using namespace std;

int main()
{
    Py_Initialize();    // 初始化

    // 將Python工作路徑切換到待調用模塊所在目錄,一定要保證路徑名的正確性
    string path = "~/test";
    string chdir_cmd = string("sys.path.append(\"") + path + "\")";
    const char* cstr_cmd = chdir_cmd.c_str();
    PyRun_SimpleString("import sys");
    PyRun_SimpleString(cstr_cmd);

    // 加載模塊
    PyObject* moduleName = PyString_FromString("test"); //模塊名,不是文件名
    PyObject* pModule = PyImport_Import(moduleName);
    if (!pModule) // 加載模塊失敗
    {
        cout << "[ERROR] Python get module failed." << endl;
        return 0;
    }
    cout << "[INFO] Python get module succeed." << endl;

    // 加載函數
    PyObject* pv = PyObject_GetAttrString(pModule, "test_add");
    if (!pv || !PyCallable_Check(pv))  // 驗證是否加載成功
    {
        cout << "[ERROR] Can't find funftion (test_add)" << endl;
        return 0;
    }
    cout << "[INFO] Get function (test_add) succeed." << endl;

    // 設置參數
    PyObject* args = PyTuple_New(2);   // 2個參數
    PyObject* arg1 = PyInt_FromLong(4);    // 參數一設為4
    PyObject* arg2 = PyInt_FromLong(3);    // 參數二設為3
    PyTuple_SetItem(args, 0, arg1);
    PyTuple_SetItem(args, 1, arg2);

    // 調用函數
    PyObject* pRet = PyObject_CallObject(pv, args);

    // 獲取參數
    if (pRet)  // 驗證是否調用成功
    {
        long result = PyInt_AsLong(pRet);
        cout << "result:" << result;
    }

    Py_Finalize();      ## 釋放資源

    return 0;
}

參數傳遞

1 C++Python 傳遞參數

Python 的參數實際上是元組,因此傳參實際上就是構造一個合適的元組。

常用的有兩種方法:

使用 PyTuple_New 創建元組, PyTuple_SetItem 設置元組值

PyObject* args = PyTuple_New(3);
PyObject* arg1 = Py_BuildValue("i", 100); // 整數參數
PyObject* arg2 = Py_BuildValue("f", 3.14); // 浮點數參數
PyObject* arg3 = Py_BuildValue("s", "hello"); // 字符串參數
PyTuple_SetItem(args, 0, arg1);
PyTuple_SetItem(args, 1, arg2);
PyTuple_SetItem(args, 2, arg3);

直接使用Py_BuildValue構造元組

PyObject* args = Py_BuildValue("ifs", 100, 3.14, "hello");
PyObject* args = Py_BuildValue("()"); // 無參函數

i, s, f之類的格式字符串可以參考 格式字符串

2 轉換 Python 返回值

調用 Python 得到的都是PyObject對象,因此需要使用 Python 提供的庫裡面的一些函數將返回值轉換為 C++ , 例如 PyInt_AsLongPyFloat_AsDoublePyString_AsString 等。

還可以使用 PyArg_ParseTuple 函數來將返回值作為元組解析。

PyArg_Parse 也是一個使用很方便的轉換函數。

PyArg_ParseTuplePyArg_Parse 都使用 格式字符串

注意事項

需要將 Python 的工作目錄切換到模塊所在路徑 按照模塊名加載而不是文件名 模塊加載或者函數加載需要驗證是否成功,否則可能會引起堆棧錯誤導致程序崩潰 需要使用 Py_DECREF(PyObject*) 來解除對象的引用(以便Python垃圾回收)
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved