[英]How to return a string with null characters from C++ DLL to Python?
[英]Return data from c++ dll with Python
我正在為 3M 文檔掃描儀的接口編程。
我正在調用一個名為MMMReader_GetData
的函數
MMMReaderErrorCode MMMReader_GetData(MMMReaderDataType aDataType,void* DataPtr,int* aDataLen);
描述:
從文檔中讀取數據項后,可以通過此 API 獲取該數據項。 aDataPtr 參數中提供的緩沖區將與數據一起寫入,並且 aDataLen 更新為數據的長度。
問題是如何創建void* DataPrt
以及如何獲取數據?
我試過了:
from ctypes import *
lib=cdll.LoadLibrary('MMMReaderHighLevelAPI.dll')
CD_CODELINE = 0
aDataLen = c_int()
aDataPtr = c_void_p()
index= c_int(0)
r = lib.MMMReader_GetData(CD_CODELINE,byref(aDataPtr),byref(aDataLen),index)
aDataLen
總是返回一個值,但aDataPtr
返回None
您的代碼有幾個問題:
aDataPtr
指向的緩沖區。aDataLen
傳遞緩沖區長度。 根據[1],如果緩沖區不夠大, MMMReader_GetData
將根據需要重新分配。aDataPtr
,而不是byref
。MMMReader_GetData
的方法描述符向方法( index
參數)傳遞一個額外的參數。請嘗試以下操作:
import ctypes
lib = ctypes.cdll.LoadLibrary('MMMReaderHighLevelAPI.dll')
CD_CODELINE = 0
aDataLen = ctypes.c_int(1024)
aDataPtr = ctypes.create_string_buffer(aDataLen.value)
err = lib.MMMReader_GetData(CD_CODELINE, aDataPtr, ctype.byref(aDataLen))
然后您可以將緩沖區的內容作為常規字符數組讀取。 實際長度在aDataLen
返回。
[1] 3M頁面閱讀器程序員指南: https : //wenku.baidu.com/view/1a16b6d97f1922791688e80b.html
您需要做的是分配一個“緩沖區”。 緩沖區的地址將作為 void* 參數傳遞,緩沖區的大小(以字節為單位)將作為aDataLen
參數傳遞。 然后函數會將它的數據放入你給它的緩沖區中,然后你可以從緩沖區中讀回數據。
在 C 或 C++ 中,您將使用malloc
或類似的東西來創建緩沖區。 使用ctypes
,可以使用ctypes.create_string_buffer制作一定長度的緩沖區,然后將緩沖區和長度傳遞給函數。 然后一旦函數填充它,您就可以從您創建的緩沖區中讀取數據,它的工作方式類似於帶有[]
和len()
的字符列表。
使用ctypes
,最好定義參數類型和返回值以進行更好的錯誤檢查,並且聲明指針類型在 64 位系統上尤其重要。
from ctypes import *
MMMReaderErrorCode = c_int # Set to an appropriate type
MMMReaderDataType = c_int # ditto...
lib = CDLL('MMMReaderHighLevelAPI')
lib.MMMReader_GetData.argtypes = MMMReaderDataType,c_void_p,POINTER(c_int)
lib.MMMReader_GetData.restype = MMMReaderErrorCode
CD_CODELINE = 0
# Make sure to pass in the original buffer size.
# Assumption: the API should update it on return with the actual size used (or needed)
# and will probably return an error code if the buffer is not large enough.
aDataLen = c_int(256)
# Allocate a writable buffer of the correct size.
aDataPtr = create_string_buffer(aDataLen.value)
# aDataPtr is already a pointer, so no need to pass it by reference,
# but aDataLen is a reference so the value can be updated.
r = lib.MMMReader_GetData(CD_CODELINE,aDataPtr,byref(aDataLen))
返回時,您可以通過字符串切片僅訪問緩沖區的返回部分,例如:
>>> from ctypes import *
>>> aDataLen = c_int(10)
>>> aDataPtr = create_string_buffer(aDataLen.value)
>>> aDataPtr.raw
'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
>>> aDataLen.value = 5 # Value gets updated
>>> aDataPtr[:aDataLen.value] # Get the valid portion of buffer
'\x00\x00\x00\x00\x00'
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.