我正在使用python ctypes和libc与供应商提供的DLL文件进行接口。 DLL文件的目的是从照相机获取图像。

图像获取似乎没有错误;正在运行。我遇到的问题是访问数据。

图像获取函数将ctypes.c_void_p用作图像数据的参数。

简化如下:

"""
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)


我不完全了解函数的功能,因为运行函数后,imageData.initial_readout似乎是'long'类型的(甚至不是ctypes.c_long:只是“长”)。但是,它也具有与之关联的值。我假设这是存储数据的起始地址。

>>> type(imageData.initial_readout)
<type 'long'>
>>> imageData.initial_readout
81002560L


我当前访问数据的方法是使用libc.fopen,libc.fwrite ,libc.fclose如下:

>>> 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)


其中readoutstride = 2097152对应于16位像素的1024x1024数组。 “显示在Windows资源管理器中,但是它有0 KB,当我尝试使用它打开文件时(例如,使用imag浏览器),它说文件为空。

我看到fwrite返回了一个值的0(但应返回值1)

如果您对我在这里做错的事情有任何想法,我将非常感谢。预先谢谢您。

评论

@eryksun我今天早上在编辑中包含了一个要获取的原型。同样,严格说来,imageData是一个结构,它包含一个空指针(我省略了这些细节以简化最初的问题)。但是,由于您已经要求我修改了上面的代码以包含完整的结构。希望这可以澄清一些事情。

@eryksun readout_count是正在收集的帧数。当我调用Acquire函数时,其第二个参数是readout_count,我将其指定为1。运行Acquire后,该值将分配给imageData.readout_count。 readoutstride指定跨度(帧)中的字节数。我可以调用一个其他函数(在获取之前),该函数返回readoutsride。它返回的值为2097152,对应于1024x1024像素时每像素2个字节。

@eryksun在我看来,确实有一个字节字符串存储在内存中(在available.initial_readout指定的地址处)。 Python中是否有一种方法可以访问从给定内存地址开始的next2097152字节,例如81002560L或十六进制0x4d40040L?

如果调用成功,则有很多创建字符串的方法。一种方法是使用ctypes.string_at(address,size)之后,调用释放内存的库函数。

#1 楼

指定功能的argtypesrestype

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的规范。我仍然遇到同样的问题-请随时查看我对上述问题的更新。感谢您查看这个。

–乔
2013年6月23日15:09

@ J.Lowney,您必须指定argtypes,不仅要对fopen,fwrite,fclose进行restype的转换,还必须对...进行获取。

– falsetru
2013年6月23日15:15

@ J.Lowney,将ctypes.c_void_p(available.initial_readout)更改为ctypes.addressof(available.initial_readout)。

– falsetru
2013年6月23日15:16

当我修改为ctypes.addressof(imageData.initial_readout)时,出现错误:TypeError:无效的类型。令人困惑的部分是,在将结构传递给函数之前,available.initial_readout被定义为ctypes.c_void_p。当我从函数取回它时,它的类型很长-所以我认为python正在将其转换回python变量。结果,我认为我已经丢失了ctypes.addressof信息。

–乔
2013年6月23日15:40



argstype,argtypes和argstypes是否以某种方式别名?我似乎在互联网上找到了所有(虽然大多数是argtypes)。

– Shahbaz
2015年3月23日在16:59