在ctypes中部分定义Struct定义
Partially define Struct definition in ctypes
我不熟悉 Python-C 接口,我正在使用 C SDK。
有一个名为 NET_ITS_PLATE_RESULT
的结构,我只需要从 API 回调函数中检索 dwSize
和 byPicNo
。
在我的回调函数(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).
此外,考虑到程序将通过上述阶段,由于您删除了一些字段(dwMatchNo、byGroupNum),你不会在 byPicNo 中得到正确的数据,但是 dwMatchNo 的 1st 字节。
所以,永远不要走这样的捷径,除非你真的知道你在做什么以及处理它们的代码做了什么 - 这似乎并不就这样吧。
嗯,看着 dwSize 成员,我正在考虑 MS 结构(例如 [MS.Docs]: OSVERSIONINFOEXW structure),其 1st 成员是它们的大小,在将结构(指针)传递给正在填充其 (相关)成员。检查这种情况也会很有趣。但无论如何,它不可能与提议的 NET_ITS_PLATE_RESULT.
一起工作
我不熟悉 Python-C 接口,我正在使用 C SDK。
有一个名为 NET_ITS_PLATE_RESULT
的结构,我只需要从 API 回调函数中检索 dwSize
和 byPicNo
。
在我的回调函数(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).
此外,考虑到程序将通过上述阶段,由于您删除了一些字段(dwMatchNo、byGroupNum),你不会在 byPicNo 中得到正确的数据,但是 dwMatchNo 的 1st 字节。
所以,永远不要走这样的捷径,除非你真的知道你在做什么以及处理它们的代码做了什么 - 这似乎并不就这样吧。
嗯,看着 dwSize 成员,我正在考虑 MS 结构(例如 [MS.Docs]: OSVERSIONINFOEXW structure),其 1st 成员是它们的大小,在将结构(指针)传递给正在填充其 (相关)成员。检查这种情况也会很有趣。但无论如何,它不可能与提议的 NET_ITS_PLATE_RESULT.
一起工作