C++ 和嵌入式Python - NUL终止字符串
我正在把Python 2.6嵌入到一个现有的C++应用程序中。目前,我已经成功链接了相关的库,并能够初始化Python解释器,还能把数据传递给Python。不过,我在获取数据时遇到了一些麻烦,希望有人能给我指个方向。我正在使用以下代码:
Py_Initialize();
pModule = PyImport_ImportModule("cBuffers"); // This crashes after 1st call.
pDict = PyModule_GetDict(pModule);
pClass = PyDict_GetItemString(pDict, "rf_pdf");
pMeth = PyString_FromString("main");
if (PyCallable_Check(pClass) && PyClass_Check(pClass)) {
pInstance = PyInstance_New(pClass, NULL, NULL);
pOutput = PyObject_CallMethodObjArgs(pInstance, pMeth, pOpts, pInput, NULL);
}
if (pOutput != NULL) {
string pPdf = PyString_AsString(pOutput);
Py_DECREF(pOutput);
} else {
PyErr_Print();
}
// Cleanup
Py_DECREF(pModule);
Py_DECREF(pModule); // Has an extra reference, not positive why.
Py_DECREF(pMeth);
Py_DECREF(pInstance);
Py_DECREF(pOpts);
Py_DECREF(pInput);
Py_Finalize();
pOpts和pInput都是通过PyString_FromString
在代码的早些时候生成的。我的问题是,当我尝试用PyString_AsString来获取输出时,返回的值是以NUL(空字符)结束的。可惜的是,由于我正在生成PDF文档,NUL字符不仅是被允许的,几乎是必然会出现的。有人能告诉我如何从Python返回字符串数据到C++,而不在遇到第一个NUL字符时就结束吗?
另外,我还有一个问题,这段代码可以被多次调用,作为一个后台服务的一部分,用来从接收到的打印数据创建PDF文档。第一次调用这段代码时,一切正常。但之后的调用在Py_Initialize()
之后的某一行就失败了。如果有人能帮我弄清楚发生了什么,我将非常感激。谢谢!
1 个回答
几点建议:
不要使用字符串。虽然你可能通过一些复杂的操作让它们在这里工作,但这并不是你想要的。你应该把数据存储在一个自定义的数据结构(或者一个缓冲区)中,这个结构只是字节的序列(你真的希望客户端在Python中对这些数据进行字符串操作吗?)。如果你的对象确实是一个缓冲区对象,应该使用缓冲区API。
你导入的模块的引用计数是2,因为它被保存在
sys.modules
中(为了下次导入时的效率)。绝对不要减少你不拥有的引用计数,否则会导致程序崩溃。文档中的导入模块部分应该涵盖这个内容,但实际上并没有。每次进行这些操作时,初始化和关闭Python是非常耗费资源的。你应该尝试重新组织你的使用场景,这样可以在应用程序启动时(或者第一次需要Python时)只调用一次
Py_Initialize
,然后只有在应用程序确实完成Python的使用时,或者在退出时才调用Py_Finalize
。你在错误检查上做得很不够——大多数Python C/API函数可以返回NULL来表示发生了异常,而你几乎从不检查这个值。如果某些操作失败,你会在很奇怪的地方崩溃。你可以在C/API手册的异常处理部分阅读相关内容。