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

(

)

初始化和關閉

Python

直譯器

#include

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