如何正确解析ctypes中的嵌套结构

2024-09-30 02:24:59 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在开发一个C SDK,需要从嵌套的struct中检索结果。我没有一个好的方式来描述它,但这里去

它从一个回调函数开始,我需要将返回的值(lCommand)映射到它对应的函数。你知道吗

如果lCommand == 0x2800,则对应的结构是NET_DVR_PLATE_RESULT,我需要为它创建一个对象,然后引用内存地址。在NET_DVR_PLATE_RESULT内部,有另一个结构NET_DVR_PLATE_INFO,我需要检索一个名为sLicense的变量

char sLicense[16];

我期望得到ABC 123这样的结果,但是它给出了一个bytesb'\xf4\xfd\x14?#\xdb\x19?\x9c\xc4 >%\x06\x81='。你知道吗

您可以下载sdk here并搜索此方法: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()

Tags: netcallbacksdkresultbyteprintdvrplate
1条回答
网友
1楼 · 发布于 2024-09-30 02:24:59

我通读了SDK文档,相信SDK是在Windows环境下编写的。你知道吗

根据ctypes documentation

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.

我注意到结构定义中的一些参数被声明为类型c_ulong,在SDK中被声明为DWORD。您可能需要验证开发平台中是否正确提供了字段类型。你知道吗

除此之外,请确保为所有涉及的结构声明完整的结构定义。否则会得到不正确的结果,甚至分割错误。你知道吗

相关问题 更多 >

    热门问题