深入淺析 C++ 調用 Python 模組_C 語言

來源:互聯網
上載者:User

一般開發過遊戲的都知道Lua和C++可以很好的結合在一起,取長補短,把Lua指令碼當成類似動態連結程式庫來使用,很好的利用了指令碼開發的靈活性。而作為一門流行的通用型指令碼語言Python,也是可以做到的。在一個C++應用程式中,我們可以用一組外掛程式來實現一些具有統一介面的功能,一般外掛程式都是使用動態連結程式庫實現,如果外掛程式的變化比較頻繁,我們可以使用Python來代替動態連結程式庫形式的外掛程式(堪稱文本形式的動態連結程式庫),這樣可以方便地根據需求的變化改寫指令碼代碼,而不是必須重新編譯連結二進位的動態連結程式庫。靈活性大大的提高了。

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

Python 提供了 C++ 庫,使得開發人員能很方便地從 C++ 程式中調用 Python 模組。

具體的文檔參考官方指南:

Embedding Python in Another Application

調用方法

1 連結到 Python 調用庫

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

使用之前需要連結到此庫。

2 直接調用 Python 語句

<code class="language-cpp hljs ">#include "python/Python.h"int main(){Py_Initialize(); ## 初始化PyRun_SimpleString("print 'hello'");Py_Finalize(); ## 釋放資源}</code>

3 載入 Python 模組並調用函數

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

<code class="language-python hljs ">def test_add(a, b):print 'add ', a, ' and ', breturn a+b</code>

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

<code class="language-cpp hljs ">#include "python/Python.h"#include <iostream>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); // 參數一設為4PyObject* arg2 = PyInt_FromLong(3); // 參數二設為3PyTuple_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;}</iostream></code>

參數傳遞

1 C++ 向 Python 傳遞參數

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

常用的有兩種方法:

使用 PyTuple_New 建立元組, PyTuple_SetItem 設定元組值

<code class="language-cpp hljs ">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);</code>

直接使用Py_BuildValue構造元組

<code class="language-cpp hljs ">PyObject* args = Py_BuildValue("ifs", 100, 3.14, "hello");PyObject* args = Py_BuildValue("()"); // 無參函數</code>

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

2 轉換 Python 傳回值

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

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

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

PyArg_ParseTuple 和 PyArg_Parse 都使用 格式字串

注意事項

需要將 Python 的工作目錄切換到模組所在路徑 按照模組名載入而不是檔案名稱 模組載入或者函數載入需要驗證是否成功,否則可能會引起堆棧錯誤導致程式崩潰 需要使用 Py_DECREF(PyObject*) 來解除對象的引用(以便Python記憶體回收)

以上所述是小編給大家介紹的C++ 調用 Python 模組的相關知識,希望對大家有所協助!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.