2010-10-08 48 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