適合輕量級調用,無第三方依賴,但需手動管理引用計數、錯誤檢查、類型轉換,代碼冗長且易出錯。
Py_Initialize() 初始化解釋器。PyObject* func(PyObject*, PyObject*),用 PyArg_ParseTuple 解析參數,Py_BuildValue 構造返回值。PyMethodDef 表,調用 Py_InitModule("HostAPI", methods) 註冊模塊。PyImport_Import 導入 Python 腳本模塊 (如 helloworld.py)。PyModule_GetDict 獲取函數對象,PyObject_CallObject 調用。PyInt_AS_LONG 等,最後 Py_XDECREF 釋放引用,Py_Finalize 清理。
// C++ 註冊函數
PyObject* RepeatString(PyObject*, PyObject* args) {
char* str; int count;
PyArg_ParseTuple(args, "si", &str, &count);
for(int i=0;i
提供聲明式語法,自動處理類型轉換、異常傳播、智能指針綁定、繼承體系暴露,代碼極其簡潔。
#include
using namespace boost::python;
class Sample { int v; public: Sample(int v=0):v(v) {} int get() {return v;} void set(int v){this->v=v;} };
BOOST_PYTHON_MODULE(pySample) {
class_("Sample")
.def("get", &Sample::get)
.def("set", &Sample::set);
register_ptr_to_python>(); // 支持 shared_ptr 自動生命周期
}
int main() {
Py_Initialize();
initpySample(); // 模塊初始化函數
try {
object main = import("__main__");
object ns = main.attr("__dict__");
shared_ptr ptr(new Sample(25));
ns["sample"] = ptr; // 注入 C++ 對象
exec_file("sample.py", ns, ns); // 運行腳本
printf("C++ side: %d, refs: %d\n", ptr->get(), ptr.use_count());
} catch(error_already_set&) { PyErr_Print(); }
Py_Finalize();
return 0;
}
print "print in python", sample.get()
print sample
sample.set(12345)
print in python 25
print in c: 12345 2
Before finalize
Delete sample address is ...
After finalize
| 特性 | 原生 API | Boost.Python |
|---|---|---|
| 樣板代碼量 | 大 | 極小 |
| 類/繼承暴露 | 手動實現 | 原生支持 |
| 智能指針 | 無 | register_ptr_to_python |
| 異常傳播 | 手動 PyErr_SetString | 自動 C++ ↔ Python 轉換 |
| 編譯依賴 | 僅 Python.h | 需 Boost 庫 |