使用pythonctypes和libc编写指向二进制文件的void指针

使用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

我使用PythoncTypes和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)
>>> 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是一个结构,然后包含一个空指针(为了简化最初的问题,我省略了这些细节)。但是,既然您要求,我已经修改了上面的代码,以包含完整的结构。希望这能澄清问题。@eryksun
readeat\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)
然后调用库中释放内存的函数。