| 方式 | 原理 | 優點 | 缺點 |
|---|---|---|---|
| 嵌入式 Python (Python.h) | 進程內加載 Python 解釋器 | 高性能、直接數據交換、共享內存 | 編譯鏈接複雜、版本綁定、GIL 限制 |
| 系統調用 (popen/system) | 啟動獨立 Python 進程 | 簡單、隔離性好、版本無關 | 進程開銷大、IPC 需序列化 |
-I/usr/include/python3.x (或 python3-config --includes)-lpython3.x (或 python3-config --ldflags --embed)-std=c++11Py_Initialize() 初始化解釋器PyRun_SimpleString("import sys; sys.path.append('...')") 設置模塊路徑PyImport_ImportModule("module_name") 導入模塊PyObject_GetAttrString(module, "func_name") 獲取函數對象PyTuple_Pack / Py_BuildValuePyObject_CallObject(func, args) 調用PyLong_AsLong, PyUnicode_AsUTF8 等Py_Finalize() 清理
// util.h
#ifndef UTIL_H
#define UTIL_H
#include
#include
void init_log(const char* argv);
char* exe_command(const char* cmd); // 系統調用備選
void exe_py(const std::string& module, const std::string& func, const std::vector& args);
#endif
// util.cpp
#include "util.h"
#include
#include
#include
#include
#include
#define PYTHON_LIB_PATH "~/.jumbo/lib/python2.7"
#define PYTHON_BIN_PATH "~/.jumbo/bin/python2.7"
#define MAX_LENGTH 2048
void init_log(const char* argv) {
if (!getenv("GLOG_logtostderr")) google::LogToStderr();
google::InstallFailureSignalHandler();
google::InitGoogleLogging(argv);
LOG(INFO) << "Log initialized";
}
char* exe_command(const char* cmd) {
FILE* fp = popen(cmd, "r");
if (!fp) { LOG(FATAL) << "popen failed: " << cmd; return nullptr; }
char* buf = (char*)malloc(MAX_LENGTH);
fread(buf, 1, MAX_LENGTH-1, fp);
buf[strlen(buf)-1] = '\0'; // 去掉換行
pclose(fp);
return buf;
}
void exe_py(const std::string& module, const std::string& func, const std::vector& args) {
// 構造命令行調用(系統調用版,簡單可靠)
std::string args_str;
for (auto& a : args) args_str += "\"" + a + "\",";
std::string cmd = "LD_LIBRARY_PATH=" PYTHON_LIB_PATH ":$LD_LIBRARY_PATH " PYTHON_BIN_PATH " -c "
"'import sys; sys.path.append(\"pyfiles\"); import " + module + "; ret = " + module + "." + func + "([" + args_str + "])'";
LOG(INFO) << "Executing: " << cmd;
char* res = exe_command(cmd.c_str());
// 解析 res...
free(res);
}
// 真正嵌入式調用版本(需鏈接 libpython)
void exe_py_embedded(const std::string& module, const std::string& func, const std::vector& args) {
Py_Initialize();
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append(\"./pyfiles\")");
PyObject* pModule = PyImport_ImportModule(module.c_str());
if (!pModule) { PyErr_Print(); Py_Finalize(); return; }
PyObject* pFunc = PyObject_GetAttrString(pModule, func.c_str());
if (!pFunc || !PyCallable_Check(pFunc)) { PyErr_Print(); Py_DECREF(pModule); Py_Finalize(); return; }
PyObject* pArgs = PyTuple_New(args.size());
for (size_t i = 0; i < args.size(); i++)
PyTuple_SetItem(pArgs, i, PyUnicode_FromString(args[i].c_str()));
PyObject* pResult = PyObject_CallObject(pFunc, pArgs);
if (pResult) {
// 處理結果...
Py_DECREF(pResult);
} else PyErr_Print();
Py_DECREF(pArgs); Py_DECREF(pFunc); Py_DECREF(pModule);
Py_Finalize();
}
exe_command適合簡單場景、腳本隔離、避免 GIL 衝突。注意路徑、環境變量、參數轉義。
project/ ├── include/util.h ├── src/util.cpp ├── main.cpp ├── pyfiles/ # Python 模塊目錄 │ ├── printargs.py │ └── __init__.py ├── Makefile # 關鍵:-I-lpython3.x -std=c++11 └── build/
PyString vs PyUnicode)Py_INCREF/DECREF 嚴格配對PyErr_Occurred(), PyErr_Print()PyGILState_Ensure/Release 管理 GILsys.path.append 必須在導入前