我正在为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
TIA
答案 0 :(得分:2)
您的代码有几个问题:
aDataPtr
指向的缓冲区。aDataLen
中传递缓冲区长度。根据[1],如果缓冲区不够大,MMMReader_GetData
将根据需要重新分配。aDataPtr
,而不是byref
。index
的方法描述符向该方法(MMMReader_GetData
参数)传递一个额外的参数。请尝试以下操作:
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
答案 1 :(得分:2)
您需要做的是分配一个“缓冲区”。缓冲区的地址将作为void *参数传递,缓冲区的大小(以字节为单位)将作为aDataLen
参数传递。然后,该函数会将其数据放入您提供的缓冲区中,然后您可以从缓冲区中读取数据。
在C或C ++中,您将使用malloc
或类似的东西来创建缓冲区。使用ctypes
时,可以使用ctypes.create_string_buffer创建一定长度的缓冲区,然后将缓冲区和长度传递给函数。然后,一旦函数将其填充,就可以从创建的缓冲区中读取数据,该缓冲区的工作方式类似于带有[]
和len()
的字符列表。
答案 2 :(得分:2)
使用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'