標籤:

C++調用Python的API總結

C++調用Python的API總結

5 人贊了文章

最近在做C++調Python的work,簡單總結下

() 初始化和關閉Python解釋器

#include<Python.h>

Py_Initialize();

Py_Finalize();

所有的Python程序都要在這之間執行

()load Python模塊

又分為以下兩種方式

(1) 直接Load一個Python寫好的文件(假設文件名叫pytest.py, 在當前目錄下)

PyObject *pName,*pModule;

PyRun_SimpleString("import sys");//導入系統模塊

PyRun_SimpleString("sys.path.append(./)");//指定pytest.py所在的目錄

pName = PyString_FromString("pytest");//指定要導入的文件名

pModule = PyImport_Import(pName); //將pytest.py導入模塊指針pModule

(2) Load一個已經安裝好的Python模塊 (假設模塊名叫pytest)

PyObject* pModule;

pModule = PyImport_Import(PyString_FromString(「ptest」));//將pytest導入模塊指針pModule

() pModule模塊里load需要調用的函數並執行

又分為以下兩種方式

(1) 從模塊里直接load一個函數(假設函數名叫func, 有一個int型的輸入變數,返回一個int型整數)

PyObject *pfunc, *args, *results;

Pfunc= PyObject_GetAttrString(pModule,"func"); //pModule是上一步load好的Python模塊

args = Py_BuildValue("(i)",12345);//設置調用func時的輸入變數,這裡假設為12345

results= PyObject_CallObject(Pfunc, args);//執行func(12345),並將結果返回給results

(2) 從模塊里load一個類,然後調用類內部的函數 (假設類名叫Executor, 初始化需要當前文件夾下的配置文件config.txt, 函數名叫func)

PyObject *pClass, *pDict,*pInstance, *class_args,*results;

pDict = PyModule_GetDict(pModule); //拿到pModule里的所有類和函數定義

pClass=PyDict_GetItemString(pDict,"Executor");//找到名為Executor的類

class_args =Py_BuildValue("(s)","./config.txt"); //設置類初始化需要的參數

pInstance=PyInstance_New(pClass, class_args,NULL ); //初始化Executor,建立實例pInstance

results=PyObject_CallMethod(pInstance,"func","(i)",12345);// 執行pInstance.func(12345)

() C++Python傳遞參數

因為在Python中,所有的類型都經過了一層封裝,導致C++的參數需要做一個類型轉換,轉換成PyObject*才能傳入Python。例如C++的一個int就是個整數,該值佔用8bytes(64位)的存儲空間,而一個Python的int其實是一個PyObject* 指向的24bytes的結構。前8bytes是個整數,代表引用次數,中間8bytes是個指向int類型定義的指針,最後8bytes才是這個int的值。所以C++和Python之間參數的互相傳遞都需要調用Python提供的API。

假設函數的輸入變數有三個分別為一個整數(i),一個浮點數(f)和一個字元串(s)

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);

以上函數可簡化為

PyObject* args = Py_BuildValue("(ifs)",100, 3.14, "hello");

如果輸入參數是另一個Python函數的輸出結果PyObject* results (o)

PyObject* args = Py_BuildValue("(o)",results);

具體參數格式Parsing arguments and building values

() 解析Python的返回值PyObject*results

同C++傳遞參數到Python類似,調用解析函數

單個返回值:PyArg_Parse()

多返回值:PyArg_ParseTuple()

具體例子:1.7 Format Strings for PyArg_ParseTuple()

() 編譯執行

假設寫好的文件名為example_python.cpp, 想要編譯出的可執行文件叫Test, 可用命令

g++example_python.cpp -o Test -I/usr/include/python2.7/ -lpython2.7


推薦閱讀:

50多種適合機器學習和預測應用的API,你的選擇是?(2018年版本)
Mapbox 現向所有新註冊用戶開放免費API!
什麼是好用的 API 文檔
用Nodejs,GraphQL,MongoDB,Hapi和Swagger構建強大的API(一)

TAG:Python | API |