2010-10-08 16 views
1

我正在将Python 2.6嵌入到现有的C++应用程序中。到目前为止,我已经链接了库,并且能够成功初始化Python解释器,并且还可以将数据传输到Python。我无法检索它,并希望有人能引导我正确的方向。我与这方面的工作:C++和嵌入式Python - NUL终止字符串

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 Terminated。不幸的是,因为我正在生成PDF文档,所以NUL不仅被允许,它们几乎可以保证。任何人都可以告诉我如何将Python数据库中的字符串数据返回到C++,而不会在第一次遇到NUL时结束?

作为一个附加问题,此代码可作为从传入打印数据创建PDF文档的后台服务的一部分多次调用。第一次调用这个代码时,它可以正常工作。在Py_Initialize()之后的任何后续呼叫都会失败。有关如何确定发生的事情的帮助也将得到最多赞赏。在此先感谢,

+0

NULL!= ASCII NUL。 NULL是一个空指针,NUL是你的字符串终结符。最好不要混淆两者! – LukeN 2010-10-08 17:47:13

+0

@LukeN - 更新并感谢指出这两者是截然不同的,但问题仍然是从Python返回的字符串包含它们,我需要知道如何解决它。 – 2010-10-08 17:58:08

回答

1

的几点:

  • 不要使用字符串。你甚至可以使 能够使它们在这里工作,并在* _StringAndSize() 函数上产生一些 扭曲,但它不会成为你想要的东西 。您应该将数据存储在 的一个自定义数据结构(或缓冲区)中,该数据结构只是一个字节序列(您真的 希望客户端在Python中对此数据执行字符串操作 ?)。如果你的对象确实是一个缓冲对象,你应该使用Buffer API

  • 您导入的模块的refcount为2,因为它被保存在 sys.modules(为了下次尝试导入时的效率)。 从来没有 decref 引用你没有,否则你会 崩溃你的程序。 文档的Importing Modules部分应该确实包含 这个,但它不包含。

  • 每次执行这些操作时,初始化Python并将其撕下非常昂贵。您应该尝试重新组织您的用例,以便在应用程序启动时(或第一次需要Python时)只能调用Py_Initialize,然后只在应用程序为时调用Py_Finalize,肯定用Python完成,或者退出时。

  • 您对错误检查非常懒惰 - 大多数Python C/API函数都可以返回NULL来指示引发了异常,并且您几乎从不检查此值。如果失败了,你会在非常奇怪的地方开始崩溃。您可以在C/API手册的Exception Handling部分阅读这方面的内容。

+0

Nick - 1。是的,我确实需要Python中的字符串操作。 2.当我注意到额外的引用时,我加入了额外的Py_DECREF,但代码第二次通过w /或w/o来崩溃。 3和4.我没有计划离开实例化或错误检查的目前状态,但在进一步深入之前需要一个概念证明。 – 2010-10-08 18:53:58

+0

Nick - 同样在1 - 执行PDF生成的库需要一个文件句柄来放入数据。我在Python中使用StringIO实例来保持磁盘不变,然后当我完成PDF生成时,我使用'outfile.getvalue()'检索缓冲区内容。我至今无法将其转换为bytearray - 我得到一个编码错误。 – 2010-10-08 18:55:23

+0

您可以在C++中实现一个非常小的对象,它看起来像Python的类文件对象(仅通过实现适当的协议方法)并使用该对象而不是StringIO实例。这样,您可以将数据保存在内存中,但不必担心空字节或API处理,因为当客户端将它返回给您时,它已经是本机C++数据结构。 – 2010-10-08 19:55:37