如何正确解析ctypes中的嵌套结构
How to properly parse nested Structure in ctypes
我正在开发 C SDK,我需要从嵌套 struct
中检索结果。我没有很好的方式来描述它,但是这里是
它以回调函数开始,我需要将返回的值 (lCommand
) 映射到其对应的函数。
如果lCommand == 0x2800
,对应的struct是NET_DVR_PLATE_RESULT
,我需要为它创建一个对象,然后引用内存地址。在 NET_DVR_PLATE_RESULT
中,还有另一个结构 NET_DVR_PLATE_INFO
,我需要检索一个名为 sLicense
的变量
char sLicense[16];
我期待像 ABC 123
这样的结果,但它给出了 bytes
值,b'\xf4\xfd\x14?#\xdb\x19?\x9c\xc4 >%\x06\x81='
。
你可以下载sdkhere然后搜索这个方法:NET_DVR_SetDVRMessageCallBack_V31
代码
class NET_DVR_ALARMER(Structure):
_fields_ = [
("byUserIDValid", c_byte)
]
class NET_DVR_PLATE_INFO(Structure):
_fields_ = [
("byPlateType", c_byte),
("byColor", c_byte),
("byBright", c_byte),
("byLicenseLen", c_byte),
("byEntireBelieve", c_byte), # accuracy
("byRegion", c_byte),
("byCountry", c_byte),
("byRes", c_byte*24),
("dwXmlLen", c_ulong),
("sLicense", c_char*16),
("byBelieve", c_char*16) # accuracy of every recognizing character
]
class NET_DVR_PLATE_RESULT(Structure):
_fields_ = [
("dwSize", c_ulong),
("byResultType", c_byte),
("byChanIndex", c_byte),
("wAlarmRecordID", c_ushort),
("dwRelativeTime", c_ulong),
("byAbsTime", c_byte*32),
("byTrafficLight", c_byte),
("byPicNum", c_byte),
("byDriveChan", c_byte),
("byVehicleType", c_byte),
("byRes3", c_byte*8),
("struPlateInfo", NET_DVR_PLATE_INFO)
]
def MsgCallback(lCommand, pAlarmer, pAlarmInfo, dwBufLen, pUser):
messageType = str(hex(lCommand))
if messageType == "0x2800":
struPlateResult = NET_DVR_PLATE_RESULT()
memmove(pointer(struPlateResult), pAlarmInfo, sizeof(struPlateResult))
struPlateInfo = struPlateResult.struPlateInfo
print("Accuracy: {}".format(struPlateInfo.byEntireBelieve))
print("License Plate: {}".format(struPlateInfo.sLicense))
print("License Plate Length: {}".format(struPlateInfo.byLicenseLen))
return True
def setDVRMsgCallback(sdk):
callback_t = CFUNCTYPE(c_bool, c_long, POINTER(NET_DVR_ALARMER), c_void_p, c_ulong, c_void_p)
sdk.NET_DVR_SetDVRMessageCallBack_V31.restype = c_bool
if sdk.NET_DVR_SetDVRMessageCallBack_V31(callback_t(MsgCallback)):
print("Init callback event")
else:
print("Unable to init NET_DVR_SetDVRMessageCallBack_V31")
print(sdk.NET_DVR_GetLastError())
if __main__:
sdk = SDK(ip="192.168.0.246", port="8000")
setupSuccess = False
while not setupSuccess:
setDVRMsgCallback(sdk) # setup callback methods
sleep(1) # give device some time to adapt new requests
setupSuccess = NET_DVR_SetupAlarmChan_V41(sdk, lUserID) # initiate alarm
sleep(0.5)
sleep(1000)
sdk.logout(lUserID)
sdk.cleanup()
我通读了 SDK 文档,我相信 SDK 是在 Windows 环境中编写的。
c_int represents the C signed int datatype. The constructor accepts an optional integer initializer; no overflow checking is done. On platforms where sizeof(int) == sizeof(long) it is an alias to c_long.
我注意到在 SDK 中声明为 DWORD
的结构定义中的一些参数被声明为 c_ulong
类型。您可能想要验证您的开发平台是否正确提供了字段类型。
除此之外,请确保为所有涉及的结构声明完整的结构定义。否则你会得到不正确的结果甚至分段错误。
我正在开发 C SDK,我需要从嵌套 struct
中检索结果。我没有很好的方式来描述它,但是这里是
它以回调函数开始,我需要将返回的值 (lCommand
) 映射到其对应的函数。
如果lCommand == 0x2800
,对应的struct是NET_DVR_PLATE_RESULT
,我需要为它创建一个对象,然后引用内存地址。在 NET_DVR_PLATE_RESULT
中,还有另一个结构 NET_DVR_PLATE_INFO
,我需要检索一个名为 sLicense
char sLicense[16];
我期待像 ABC 123
这样的结果,但它给出了 bytes
值,b'\xf4\xfd\x14?#\xdb\x19?\x9c\xc4 >%\x06\x81='
。
你可以下载sdkhere然后搜索这个方法:NET_DVR_SetDVRMessageCallBack_V31
代码
class NET_DVR_ALARMER(Structure):
_fields_ = [
("byUserIDValid", c_byte)
]
class NET_DVR_PLATE_INFO(Structure):
_fields_ = [
("byPlateType", c_byte),
("byColor", c_byte),
("byBright", c_byte),
("byLicenseLen", c_byte),
("byEntireBelieve", c_byte), # accuracy
("byRegion", c_byte),
("byCountry", c_byte),
("byRes", c_byte*24),
("dwXmlLen", c_ulong),
("sLicense", c_char*16),
("byBelieve", c_char*16) # accuracy of every recognizing character
]
class NET_DVR_PLATE_RESULT(Structure):
_fields_ = [
("dwSize", c_ulong),
("byResultType", c_byte),
("byChanIndex", c_byte),
("wAlarmRecordID", c_ushort),
("dwRelativeTime", c_ulong),
("byAbsTime", c_byte*32),
("byTrafficLight", c_byte),
("byPicNum", c_byte),
("byDriveChan", c_byte),
("byVehicleType", c_byte),
("byRes3", c_byte*8),
("struPlateInfo", NET_DVR_PLATE_INFO)
]
def MsgCallback(lCommand, pAlarmer, pAlarmInfo, dwBufLen, pUser):
messageType = str(hex(lCommand))
if messageType == "0x2800":
struPlateResult = NET_DVR_PLATE_RESULT()
memmove(pointer(struPlateResult), pAlarmInfo, sizeof(struPlateResult))
struPlateInfo = struPlateResult.struPlateInfo
print("Accuracy: {}".format(struPlateInfo.byEntireBelieve))
print("License Plate: {}".format(struPlateInfo.sLicense))
print("License Plate Length: {}".format(struPlateInfo.byLicenseLen))
return True
def setDVRMsgCallback(sdk):
callback_t = CFUNCTYPE(c_bool, c_long, POINTER(NET_DVR_ALARMER), c_void_p, c_ulong, c_void_p)
sdk.NET_DVR_SetDVRMessageCallBack_V31.restype = c_bool
if sdk.NET_DVR_SetDVRMessageCallBack_V31(callback_t(MsgCallback)):
print("Init callback event")
else:
print("Unable to init NET_DVR_SetDVRMessageCallBack_V31")
print(sdk.NET_DVR_GetLastError())
if __main__:
sdk = SDK(ip="192.168.0.246", port="8000")
setupSuccess = False
while not setupSuccess:
setDVRMsgCallback(sdk) # setup callback methods
sleep(1) # give device some time to adapt new requests
setupSuccess = NET_DVR_SetupAlarmChan_V41(sdk, lUserID) # initiate alarm
sleep(0.5)
sleep(1000)
sdk.logout(lUserID)
sdk.cleanup()
我通读了 SDK 文档,我相信 SDK 是在 Windows 环境中编写的。
c_int represents the C signed int datatype. The constructor accepts an optional integer initializer; no overflow checking is done. On platforms where sizeof(int) == sizeof(long) it is an alias to c_long.
我注意到在 SDK 中声明为 DWORD
的结构定义中的一些参数被声明为 c_ulong
类型。您可能想要验证您的开发平台是否正确提供了字段类型。
除此之外,请确保为所有涉及的结构声明完整的结构定义。否则你会得到不正确的结果甚至分段错误。