使用pythonctypes和libc编写指向二进制文件的void指针
我使用PythoncTypes和libc与供应商提供的DLL文件进行接口。DLL文件的用途是从相机获取图像 图像采集似乎运行无误;我遇到的问题是访问数据 图像采集函数将ctypes.c_void_p作为图像数据的参数 简化如下:使用pythonctypes和libc编写指向二进制文件的void指针,python,ctypes,fwrite,void-pointers,libc,Python,Ctypes,Fwrite,Void Pointers,Libc,我使用PythoncTypes和libc与供应商提供的DLL文件进行接口。DLL文件的用途是从相机获取图像 图像采集似乎运行无误;我遇到的问题是访问数据 图像采集函数将ctypes.c_void_p作为图像数据的参数 简化如下: """ typedef struct AvailableData { void* initial_readout; int64 readout_count; } imageData; """ class AvailableData(ctypes.Str
"""
typedef struct AvailableData
{
void* initial_readout;
int64 readout_count;
} imageData;
"""
class AvailableData(ctypes.Structure):
_fields_ = [("initial_readout", ctypes.c_void_p),
("readout_count", ctypes.c_longlong)]
"""
Prototype
Acquire(
CamHandle camera,
int64 readout_count,
int readout_time_out,
AvailableData* available,
AcquisitionErrorsMask* errors );
"""
>>> imageData = AvailableData()
>>> Acquire.argtypes = CamHandle, ctypes.c_longlong, ctypes.c_int,
ctypes.POINTER(AvailableData), ctypes.POINTER(AcquisitionErrorsMask)
>>> Acquire.restype = ctypes.c_void_p
>>> status = Acquire(camera, readout_count, readout_time_out, imageData, errors)
>>> libc = ctypes.cdll.msvcrt
>>> fopen = libc.fopen
>>> fwrite = libc.fwrite
>>> fclose = libc.fclose
>>> fopen.argtypes = ctypes.c_char_p, ctypes.c_char_p
>>> fopen.restype = ctypes.c_void_p
>>> fopen.restype = ctypes.c_void_p
>>> fwrite.argtypes = ctypes.c_void_p, ctypes.c_size_t, ctypes.c_size_t, ctypes.c_void_p
>>> fwrite.restype = ctypes.c_size_t
>>> fclose = libc.fclose
>>> fclose.argtypes = ctypes.c_void_p,
>>> fclose.restype = ctypes.c_int
>>> fp = fopen('output3.raw', 'wb')
>>> print 'fwrite returns: ',fwrite(ctypes.c_void_p(imageData.initial_readout), readoutstride.value, 1, fp)
fwrite returns: 0
>>> fclose(fp)
我不完全理解函数的具体功能,因为在我运行函数之后,imageData.initial_readout
似乎是一个“long”类型(甚至不是ctypes.c_long:只是“long”)。但是,它也有一个与之关联的值。我假设这是存储数据的起始地址
>>> type(imageData.initial_readout)
<type 'long'>
>>> imageData.initial_readout
81002560L
其中,readoutstride=2097152
对应于16位像素的1024x1024数组
文件“output3.raw”显示在windows资源管理器中,但是,它有0 KB,当我尝试使用(例如,使用imag查看器)打开它时,它表示该文件为空。
我看到fwrite
返回值0(但应该返回值1)
如果你知道我做错了什么,我非常感激。提前感谢。指定函数的
argtypes
,restype
import ctypes
libc = ctypes.windll.msvcrt
fopen = libc.fopen
fopen.argtypes = ctypes.c_char_p, ctypes.c_char_p,
fopen.restype = ctypes.c_void_p
fwrite = libc.fwrite
fwrite.argtypes = ctypes.c_void_p, ctypes.c_size_t, ctypes.c_size_t, ctypes.c_void_p
fwrite.restype = ctypes.c_size_t
fclose = libc.fclose
fclose.argtypes = ctypes.c_void_p,
fclose.restype = ctypes.c_int
fp = fopen('output3.raw', 'wb')
fwrite('Hello', 5, 1, fp)
fclose(fp)
我修改了代码以包含
argstypes
和restype
的规范。我仍然有同样的问题——请随时查看我对上述问题的更新。感谢您的关注。@J.Lowney,您必须指定argtypes,不仅为fopen、fwrite、fclose重新键入,而且还要获取,…@J.Lowney,将ctypes.c\u void\u p(可用的.initial\u读出)
更改为ctypes.addressof(可用的.initial\u读出)
。当我修改为ctypes.addressof(imageData.initial\u读出)时
我收到一个错误:TypeError:invalid type
。令人困惑的是,在我将结构传递给函数之前,可用。初始读数被定义为ctypes.c\u void\u p
。当我从函数中得到它时,它是一个类型long
——因此我认为python正在将它转换回python变量。因此,我认为我丢失了ctypes.addressof
信息。是argstype
、argtypes
和argstypes
的别名吗?我似乎在互联网上找到了所有信息(大部分是argtypes
)@eryksun我在今天早上的编辑中加入了acquire的原型。另外,严格来说,imageData是一个结构,然后包含一个空指针(为了简化最初的问题,我省略了这些细节)。但是,既然您要求,我已经修改了上面的代码,以包含完整的结构。希望这能澄清问题。@eryksunreadeat\u count
是收集的帧数。当我调用Acquire
函数时,它的第二个参数是readout\u count
,我指定为1。运行Acquire
后,该值被分配给imageData.readout\u count
<代码>读取超出跨距
指定跨距(帧)中的字节数。我还可以调用一个附加函数(在获取之前),该函数返回readoutsride
。它返回的值是2097152
,对应于1024x1024像素处的每像素2个字节。@eryksun在我看来,内存中确实存储了一个字节字符串(在available.initial\u readout给出的地址)。Python中是否有方法访问从给定内存地址开始的下一个2097152
字节,例如81002560L
或十六进制0x4d40040L
?如果调用成功,有很多方法可以创建字符串。一种方法是使用ctypes.string_at(address,size)
然后调用库中释放内存的函数。