總結:python使用ctypes模塊調用C++動態(tài)庫,未設置參數的接收類型而引發(fā)的BUG
一传睹、宇視SDK抓圖流程
NETDEV_Init 初始化
NETDEV_Login_V30 ipc設備登錄
NETDEV_QueryVideoChlDetailList 查詢視頻通道信息列表
NETDEV_CaptureNoPreview 設備抓圖
image.png
二、python code
使用restype 設置接收參數的類型
HIKSDK.NETDEV_Login_V30.restype = ctypes.c_void_p
假如不設置接收參數的類型瞎疼,會拋出異常:內存地址不一致
def _uni_login(address, username, password, port, channel):
HIKSDK.NETDEV_Init()
pst_dev_login_info = NETDEVDeviceLoginInfo()
pst_dev_login_info.szIPAddr = bytes(address, "ascii")
pst_dev_login_info.szUserName = bytes(username, "ascii")
pst_dev_login_info.szPassword = bytes(password, "ascii")
pst_dev_login_info.dwPort = port
pst_dev_login_info.dwLoginProto = 0
pst_dev_login_info.dwDeviceType = 1
pst_security_login_info = NETDEVSELogInfo()
login_info_1 = byref(pst_dev_login_info)
login_info_2 = byref(pst_security_login_info)
HIKSDK.NETDEV_Login_V30.restype = ctypes.c_void_p # 設定接收登錄的參數類型為c_void_p
lUserID = HIKSDK.NETDEV_Login_V30(login_info_1, login_info_2)
if lUserID == 0:
logging.error("unisdk failed to login (%s): %s", address, _errmsg())
logging.debug('unisdk._uni_login: login success:loginID = {}'.format(lUserID))
channel_info = NETDEVVideoChlDetailInfo()
# 查詢視頻通道信息列表
channel_num = HIKSDK.NETDEV_QueryVideoChlDetailList(ctypes.c_void_p(lUserID), pointer(ctypes.c_int(channel)),
byref(channel_info))
if channel_num != True:
raise RuntimeError("unisdk failed to get channel info ({}): {}".format(address, _errmsg()))
logging.debug('unisdk._uni_login: address = {} channel_num = {}'.format(address, channel_num))
return lUserID
2.1 異常原因:
指針類型作為返回值傳遞給python時水援,在未設置類型的時候,會發(fā)生默認截斷的問題
sdk日志:
image.png
python日志:101200(用戶不在線)
image.png
三宴杀、參考連接
https://docs.python.org/3.6/library/ctypes.html#fundamental-data-types
http://icejoywoo.github.io/2018/12/10/intro-python-ctyps.html