在ctypes中部分定义Struct定义

Partially define Struct definition in ctypes

我不熟悉 Python-C 接口,我正在使用 C SDK。

有一个名为 NET_ITS_PLATE_RESULT 的结构,我只需要从 API 回调函数中检索 dwSizebyPicNo

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

class NET_ITS_PLATE_RESULT(ctypes.Structure):

    _fields_ = [
        ("dwSize", ctypes.c_uint),
        ("byPicNo", ctypes.c_byte)
    ]

来自文档:NET_ITS_PLATE_RESULT(实际定义要长得多)

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;

为简单起见,在提及结构大小时,我将忽略(默认为 4 字节)内存对齐,并表现得像它们 一个字节 对齐,以便结构的大小等于其成员大小的总和。

示例:

>>> import ctypes
>>>
>>> class Struct0(ctypes.Structure):  # Your NET_ITS_PLATE_RESULT structure, with a shorter name
...     _fields_ = [
...         ("dwSize", ctypes.c_uint),
...         ("byPicNo", ctypes.c_byte)
...     ]
...
>>>
>>>
>>> class Struct0Pack001(ctypes.Structure):
...     _pack_ = 1
...     _fields_ = [
...         ("dwSize", ctypes.c_uint),
...         ("byPicNo", ctypes.c_byte)
...     ]
...
>>>
>>> print(ctypes.sizeof(Struct0))
8
>>> print(ctypes.sizeof(Struct0Pack001))
5

当你的回调函数的调用者(你的其他问题中的SDK)将调用它时,它会尝试填充它的NET_ITS_PLATE_RESULT 参数(如果参数是指针(最有可能),则指向参数指向的内存;如果不是,则直接指向堆栈),因此写入 sizeof(NET_ITS_PLATE_RESULT) (16) 字节 - 正如它所期望的结构。

但是你只会传递 5 个字节,因此 SDK 将尝试在其 "allowed" 内存区域之外写入,从而导致 未定义的行为 。你可能会得到 segfaults (Access violations).

此外,考虑到程序将通过上述阶段,由于您删除了一些字段(dwMatchNobyGroupNum),你不会在 byPicNo 中得到正确的数据,但是 dwMatchNo 的 1st 字节。

所以,永远不要走这样的捷径,除非你真的知道你在做什么以及处理它们的代码做了什么 - 这似乎并不就这样吧。

嗯,看着 dwSize 成员,我正在考虑 MS 结构(例如 [MS.Docs]: OSVERSIONINFOEXW structure),其 1st 成员是它们的大小,在将结构(指针)传递给正在填充其 (相关)成员。检查这种情况也会很有趣。但无论如何,它不可能与提议的 NET_ITS_PLATE_RESULT.

一起工作