Python 在ctypes中部分定义结构定义

Python 在ctypes中部分定义结构定义,python,ctypes,Python,Ctypes,我不太熟悉Python-C接口,我使用的是C SDK 有一个结构称为NET\u它的\u PLATE\u结果,我只需要从API回调函数中检索dwSize和byPicNo 在回调函数(Python)中,我将使用memmove函数复制结果内存块。只定义部分struct并且仍然能够得到我想要的实际结果,这是一种好的做法吗?就像我在下面定义的那样 class NET_ITS_PLATE_RESULT(ctypes.Structure): _fields_ = [ ("dwSize

我不太熟悉Python-C接口,我使用的是C SDK

有一个结构称为
NET\u它的\u PLATE\u结果
,我只需要从API回调函数中检索
dwSize
byPicNo

在回调函数(Python)中,我将使用
memmove
函数复制结果内存块。只定义部分
struct
并且仍然能够得到我想要的实际结果,这是一种好的做法吗?就像我在下面定义的那样

class NET_ITS_PLATE_RESULT(ctypes.Structure):

    _fields_ = [
        ("dwSize", ctypes.c_uint),
        ("byPicNo", ctypes.c_byte)
    ]
从文档中:NET\u它的板\u结果(实际定义要长得多)


为了简单起见,在提到结构大小时,我将忽略(4字节默认)内存对齐,并将它们视为一个字节的对齐方式,以便结构的大小等于其成员大小之和

例如:

>>导入ctypes
>>>
>>>类Struct0(ctypes.Structure):#您的网络_其PLATE RESULT结构,名称较短
...     _字段=[
…(“dwSize”,ctypes.c_uint),
…(“byPicNo”,ctypes.c_字节)
...     ]
...
>>>
>>>
>>>类Struct0Pack001(ctypes.Structure):
...     _包装=1
...     _字段=[
…(“dwSize”,ctypes.c_uint),
…(“byPicNo”,ctypes.c_字节)
...     ]
...
>>>
>>>打印(ctypes.sizeof(Struct0))
8.
>>>打印(ctypes.sizeof(Struct0Pack001))
5.
当回调函数的调用者调用它时,它将尝试填充其NET\u-its\u-PLATE\u结果参数(如果参数是指针(很可能是指针),则填充到参数所指向的内存,如果不是指针,则直接填充到堆栈上),从而写入
sizeof(净其板结果)
16)字节—正如它所期望的那样

但是您将只传递5字节,因此SDK将尝试在其“允许”内存区域之外写入,从而导致未定义的行为。您可能会遇到SEGFULTS(访问冲突)

另外,考虑到程序将通过上述阶段,因为您删除了一些字段(dwMatchNo、byGroupNum),所以您将无法在byPicNo中获得正确的数据,而是在dwMatchNo的第一个字节中获得正确的数据

所以,永远不要选择像这样的快捷方式,除非你真的知道自己在做什么,以及处理它们的代码在做什么——这里似乎不是这样


嗯,看看dwSize成员,我想到的是MS结构(例如),其第一个成员是它们的大小,在将结构(指针)传递给正在填充其(相关)的API之前,需要相应地设置它成员们。检查这个场景也很有意思。但无论如何,它都不可能与建议的网络板结果一起工作。

为了简单起见,在提到结构大小时,我将忽略(4字节默认值)内存对齐,并像对齐一个字节一样,使结构的大小等于其成员大小之和

例如:

>>导入ctypes
>>>
>>>类Struct0(ctypes.Structure):#您的网络_其PLATE RESULT结构,名称较短
…\u字段=[
…(“dwSize”,ctypes.c_uint),
…(“byPicNo”,ctypes.c_字节)
...     ]
...
>>>
>>>
>>>类Struct0Pack001(ctypes.Structure):
…\u块=1
…\u字段=[
…(“dwSize”,ctypes.c_uint),
…(“byPicNo”,ctypes.c_字节)
...     ]
...
>>>
>>>打印(ctypes.sizeof(Struct0))
8.
>>>打印(ctypes.sizeof(Struct0Pack001))
5.
当回调函数的调用者调用它时,它将尝试填充其NET\u-its\u-PLATE\u结果参数(如果参数是指针(很可能是指针),则填充到参数所指向的内存,如果不是指针,则直接填充到堆栈上),从而写入
sizeof(净其板结果)
16)字节—正如它所期望的那样

但是您将只传递5字节,因此SDK将尝试在其“允许”内存区域之外写入,从而导致未定义的行为。您可能会遇到SEGFULTS(访问冲突)

另外,考虑到程序将通过上述阶段,因为您删除了一些字段(dwMatchNo、byGroupNum),所以您将无法在byPicNo中获得正确的数据,而是在dwMatchNo的第一个字节中获得正确的数据

所以,永远不要选择像这样的快捷方式,除非你真的知道自己在做什么,以及处理它们的代码在做什么——这里似乎不是这样


嗯,看看dwSize成员,我想到的是MS结构(例如),其第一个成员是它们的大小,在将结构(指针)传递给正在填充其(相关)的API之前,需要相应地设置它各位成员。检查此场景也很有意思。但无论如何,它都不可能与建议的网络板结果一起工作。

感谢您的详细解释!感谢您的详细解释!
struct{
  DWORD                    dwSize;
  DWORD                    dwMatchNo;
  BYTE                     byGroupNum;
  BYTE                     byPicNo;
  BYTE                     bySecondCam;
  BYTE                     byFeaturePicNo;
  BYTE                     byDriveChan;
  BYTE                     byVehicleType;
  BYTE                     byDetSceneID;
  BYTE                     byVehicleAttribute;
}NET_ITS_PLATE_RESULT, *LPNET_ITS_PLATE_RESULT;