python - 在 ctypes 中部分定义 Struct 定义
问题描述
我不精通 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将尝试在其“允许的”内存区域之外写入,从而导致未定义的行为。您可能会得到segfault(访问冲突)。
此外,考虑到程序将通过上述阶段,因为您消除了一些字段(dwMatchNo,byGroupNum),您将不会在byPicNo中获得正确的数据,而是dwMatchNo的第一个字节。
所以,永远不要选择这样的捷径,除非你真的知道你在做什么以及处理它们的代码在做什么——这似乎不是这里的情况。
嗯,看着dwSize成员,我正在考虑MS结构(例如[MS.Docs]: OSVERSIONINFOEXW 结构),其第一个成员是它们的大小,并且在将结构(指针)传递给API之前需要相应地设置它正在填充其(相关)成员。检查这种情况也会很有趣。但无论如何,它不可能与提议的NET_ITS_PLATE_RESULT 一起使用。
推荐阅读
- apache-spark - 在 HIVE 中执行查询但看不到结果
- php - 在 id base codeigniter 上加载特定的 div
- android - 如何处理 MVVM 模式和数据绑定中的适配器行点击?
- algorithm - 在测验中做出所有可能的答案组合的算法
- typescript - TS2339:“元素”类型上不存在属性“msMatchesSelector”
- ios - 当我更改数据源中的项目数时,UIcollection 视图崩溃
- sed - sed命令将逗号分隔的字符串分成一定的长度
- node.js - 会话实体在对话流的用户实体解析中的使用
- c# - 将空字段从数据表写入 xml 文件
- java - 如何在 Jetty 中添加重试到端口绑定