在 C++ 应用程序中嵌入 Python 2.6 时,遇到了问题。已经成功链接了库,能够成功初始化 Python 解释器,并且可以将数据传输到 Python。但是,在检索数据时遇到了困难,希望有人能够提供正确的方向。
解决方案
有几点需要注意:
- 不要使用字符串。
- 你导入的模块引用计数为 2,因为该计数存储在 sys.modules 中(是为了以后再次导入该模块时提高效率)。
- 初始化 Python 并每次执行这些操作时将其关闭是很昂贵的。你应该尝试重新组织你的用例,以便在应用程序启动时(或第一次需要 Python 时)只调用一次 Py_Initialize,然后仅在应用程序绝对完成使用 Python 或退出时才调用 Py_Finalize。
- 你在错误检查方面很懒惰 - 大多数 Python C/API 函数都可能返回 NULL 以指示已引发异常,你几乎从不检查此值。如果出现故障,你将在非常奇怪的地方开始崩溃。你可以在 C/API 手册的异常处理部分中阅读有关它的内容。
完整的代码如下:
#include <Python.h>
int main() {
// Initialize the Python interpreter.
Py_Initialize();
// Import the "cBuffers" module.
PyObject *pModule = PyImport_ImportModule("cBuffers");
if (pModule == NULL) {
PyErr_Print();
return -1;
}
// Get the dictionary of the module.
PyObject *pDict = PyModule_GetDict(pModule);
if (pDict == NULL) {
PyErr_Print();
Py_DECREF(pModule);
return -1;
}
// Get the "rf_pdf" class from the dictionary.
PyObject *pClass = PyDict_GetItemString(pDict, "rf_pdf");
if (pClass == NULL) {
PyErr_Print();
Py_DECREF(pModule);
Py_DECREF(pDict);
return -1;
}
// Check if the class is callable.
if (!PyCallable_Check(pClass)) {
PyErr_SetString(PyExc_TypeError, "rf_pdf is not callable");
Py_DECREF(pModule);
Py_DECREF(pDict);
Py_DECREF(pClass);
return -1;
}
// Create an instance of the class.
PyObject *pInstance = PyInstance_New(pClass, NULL, NULL);
if (pInstance == NULL) {
PyErr_Print();
Py_DECREF(pModule);
Py_DECREF(pDict);
Py_DECREF(pClass);
return -1;
}
// Create the arguments for the method call.
PyObject *pOpts = PyString_FromString("options");
PyObject *pInput = PyString_FromString("input");
// Call the "main" method of the instance.
PyObject *pOutput = PyObject_CallMethodObjArgs(pInstance,
PyString_FromString("main"), pOpts, pInput, NULL);
if (pOutput == NULL) {
PyErr_Print();
Py_DECREF(pModule);
Py_DECREF(pDict);
Py_DECREF(pClass);
Py_DECREF(pInstance);
Py_DECREF(pOpts);
Py_DECREF(pInput);
return -1;
}
// Get the string from the output object.
char *pPdf = PyString_AsString(pOutput);
if (pPdf == NULL) {
PyErr_Print();
Py_DECREF(pModule);
Py_DECREF(pDict);
Py_DECREF(pClass);
Py_DECREF(pInstance);
Py_DECREF(pOpts);
Py_DECREF(pInput);
Py_DECREF(pOutput);
return -1;
}
// Do something with the string.
// Clean up.
Py_DECREF(pModule);
Py_DECREF(pDict);
Py_DECREF(pClass);
Py_DECREF(pInstance);
Py_DECREF(pOpts);
Py_DECREF(pInput);
Py_DECREF(pOutput);
// Finalize the Python interpreter.
Py_Finalize();
return 0;
}