2017-08-12 217 views
0

我在Python 3中使用​​(作爲c導入)來執行C++共享庫。該庫使用裝入蟒蛇:使用ctypes在Python中解碼C const char *

smpLib = c.cdll.LoadLibrary(os.getcwd()+os.sep+'libsmpDyn.so') 

功能之一有extern 'C'聲明const char* runSmpModel(...)。 Python函數原型進行編碼和運行:精美

proto_SMP = c.CFUNCTYPE(c.c_char_p,...) 
runSmpModel = proto_SMP(('runSmpModel',smpLib)) 
res = runSmpModel(...) 

這一切工作,但我無法將res變量進行解碼,並獲得由C runSmpModel函數傳遞出字符串。顯示res的值(我使用ipython3)爲b'\xd0'。我在網上找到最好的解決辦法 - res.decode('utf-8')給我的錯誤:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd0 in position 0: unexpected end of data 

runSmpModel功能const char*返回值來自

std::string scenID = SMPLib::SMPModel::runModel(...); 
return scenID.c_str(); 

內runModel,如下所示它最終定義,其中scenName是輸入字符串:

auto utcBuffId = newChars(500); 
sprintf(utcBuffId, "%s_%u", scenName.c_str(), microSeconds); // catenate scenario name & time 
uint64_t scenIdhash = (std::hash < std::string>() (utcBuffId)); // hash it 

auto hshCode = newChars(100); 
sprintf(hshCode, "%032llX", scenIdhash); 
scenId = hshCode; 

此特定的值3210應該是0000000000000000BBB00C6CA8B8872E。我怎樣才能解碼這個字符串?

經過大量的進一步測試,我發現問題是從C函數傳遞的字符串的長度。如果字符串的長度不超過15個字符,則不會出現問題,但如果字符串的長度等於或大於16個字符,則不會有問題。對於最小工作實施例中,C-代碼是:

extern "C" { 
    const char* testMeSO() 
    { 
    string scenarioID = "abcdefghijklmnop"; 
    return scenarioID.c_str(); 
    } 
} 

和Python代碼是(相同smpLib的定義如上所示):

proto_TST = c.CFUNCTYPE(c.c_char_p) 
testMeSO = proto_TST(('testMeSO',smpLib)) 
res = testMeSO() 
print("Scenario ID: %s"%res.decode('utf-8')) 

這使解碼錯誤,除非任何字符從C函數中的scenarioID變量中刪除。所以看起來問題是「Python如何讀取長度超過15個字符的C char*,使用​​。

+0

一個字節不能突然變爲16.您遇到了不同的問題。 –

+0

該調用返回了一個指向以'b'\ xd0 \ x00''開頭的緩衝區的指針。如果你確實需要幫助,你將不得不爲這個功能提供文檔 - 它做了什麼,參數是什麼,它在失敗時的表現如何,等等。 – eryksun

+0

所有這些信息都是必需的 - 僅僅是關於這個返回值的信息是不合理的。我編輯了這個問題,添加了這些信息。 –

回答

0

經過幾天的調試和測試,我終於得到了這個工作,使用@Petesh發佈的第二個解決方案on this SO post我不理解爲什麼​​顯然限制選自C傳遞到15個字符(+終止= 256位?)的char *值。

本質上,該溶液是通過向C功能的額外char * buff緩衝區已經使用ctypes.create_string_buffer(32*16)以及值爲32 * 16的unsigned int buffsize創建。然後,在C函數中執行scenarioID.copy(buff,buffsize)。 python原型函數以一種明顯的方式進行修改。