最近在做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