深入淺析 C++ 調用 Python 模塊
一般開發(fā)過游戲的都知道Lua和C++可以很好的結合在一起,取長補短,把Lua腳本當成類似動態(tài)鏈接庫來使用,很好的利用了腳本開發(fā)的靈活性。而作為一門流行的通用型腳本語言Python,也是可以做到的。在一個C++應用程序中,我們可以用一組插件來實現(xiàn)一些具有統(tǒng)一接口的功能,一般插件都是使用動態(tài)鏈接庫實現(xiàn),如果插件的變化比較頻繁,我們可以使用Python來代替動態(tài)鏈接庫形式的插件(堪稱文本形式的動態(tài)鏈接庫),這樣可以方便地根據(jù)需求的變化改寫腳本代碼,而不是必須重新編譯鏈接二進制的動態(tài)鏈接庫。靈活性大大的提高了。
作為一種膠水語言,Python 能夠很容易地調用 C 、 C++ 等語言,也能夠通過其他語言調用 Python 的模塊。
Python 提供了 C++ 庫,使得開發(fā)者能很方便地從 C++ 程序中調用 Python 模塊。
具體的文檔參考官方指南:
Embedding Python in Another Application
調用方法
1 鏈接到 Python 調用庫
Python 安裝目錄下已經(jīng)包含頭文件( 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 模塊并調用函數(shù)
~/test 目錄下含有 test.py :
<code class="language-python hljs ">def test_add(a, b): print 'add ', a, ' and ', b return a+b</code>
則可以通過以下代碼調用 test_add 函數(shù) :
<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; // 加載函數(shù) 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; // 設置參數(shù) PyObject* args = PyTuple_New(2); // 2個參數(shù) PyObject* arg1 = PyInt_FromLong(4); // 參數(shù)一設為4 PyObject* arg2 = PyInt_FromLong(3); // 參數(shù)二設為3 PyTuple_SetItem(args, 0, arg1); PyTuple_SetItem(args, 1, arg2); // 調用函數(shù) PyObject* pRet = PyObject_CallObject(pv, args); // 獲取參數(shù) if (pRet) // 驗證是否調用成功 { long result = PyInt_AsLong(pRet); cout << "result:" << result; } Py_Finalize(); ## 釋放資源 return 0; } </iostream></code>
參數(shù)傳遞
1 C++ 向 Python 傳遞參數(shù)
Python 的參數(shù)實際上是元組,因此傳參實際上就是構造一個合適的元組。
常用的有兩種方法:
使用 PyTuple_New 創(chuàng)建元組, PyTuple_SetItem 設置元組值
<code class="language-cpp hljs ">PyObject* args = PyTuple_New(3); PyObject* arg1 = Py_BuildValue("i", 100); // 整數(shù)參數(shù) PyObject* arg2 = Py_BuildValue("f", 3.14); // 浮點數(shù)參數(shù) PyObject* arg3 = Py_BuildValue("s", "hello"); // 字符串參數(shù) 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("()"); // 無參函數(shù)</code>
i, s, f之類的格式字符串可以參考 格式字符串
2 轉換 Python 返回值
調用 Python 得到的都是PyObject對象,因此需要使用 Python 提供的庫里面的一些函數(shù)將返回值轉換為 C++ , 例如 PyInt_AsLong,PyFloat_AsDouble, PyString_AsString 等。
還可以使用 PyArg_ParseTuple 函數(shù)來將返回值作為元組解析。
PyArg_Parse 也是一個使用很方便的轉換函數(shù)。
PyArg_ParseTuple 和 PyArg_Parse 都使用 格式字符串
注意事項
需要將 Python 的工作目錄切換到模塊所在路徑 按照模塊名加載而不是文件名 模塊加載或者函數(shù)加載需要驗證是否成功,否則可能會引起堆棧錯誤導致程序崩潰 需要使用 Py_DECREF(PyObject*) 來解除對象的引用(以便Python垃圾回收)
以上所述是小編給大家介紹的C++ 調用 Python 模塊的相關知識,希望對大家有所幫助!
您可能感興趣的文章
- 04-02c語言沒有round函數(shù) round c語言
- 01-10深入理解約瑟夫環(huán)的數(shù)學優(yōu)化方法
- 01-10深入二叉樹兩個結點的最低共同父結點的詳解
- 01-10深入理解C++中常見的關鍵字含義
- 01-10使用C++實現(xiàn)全排列算法的方法詳解
- 01-10深入Main函數(shù)中的參數(shù)argc,argv的使用詳解
- 01-10深入第K大數(shù)問題以及算法概要的詳解
- 01-10深入解析最長公共子串
- 01-10c++中inline的用法分析
- 01-10深入理解鏈表的各類操作詳解


閱讀排行
本欄相關
- 04-02c語言函數(shù)調用后清空內(nèi)存 c語言調用
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言的正則匹配函數(shù) c語言正則表達
- 04-02c語言用函數(shù)寫分段 用c語言表示分段
- 04-02c語言中對數(shù)函數(shù)的表達式 c語言中對
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段
- 04-02C語言中怎么打出三角函數(shù) c語言中怎
- 04-02c語言調用函數(shù)求fibo C語言調用函數(shù)求
隨機閱讀
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 08-05織夢dedecms什么時候用欄目交叉功能?
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 01-11ajax實現(xiàn)頁面的局部加載
- 01-10C#中split用法實例總結
- 01-10使用C語言求解撲克牌的順子及n個骰子
- 04-02jquery與jsp,用jquery
- 01-10SublimeText編譯C開發(fā)環(huán)境設置
- 01-10delphi制作wav文件的方法