Home >Backend Development >Python Tutorial >The return value when Python calls C SDK does not meet expectations and the solution to Segmentation fault
def login(ip, port, username, password, device_info, error_code):
"""
LLONG CLIENT_Login(
char *pchDVRIP, WORD wDVRPort,
char *pchUserName, char *pchPassword,
LPNET_DEVICEINFO lpDeviceInfo, int *error = 0);
:param ip:
:param port:
:param username:
:param password:
:param device_info:
:param error_code:
:return: LLONG
"""
ip_buffer = c_buffer(ip)
# ip_buffer.encode('utf8')
# user_id = c_longlong(0)
user_id = SDK._dll.CLIENT_Login( byref(ip_buffer), port, username, password, byref(device_info), byref(error_code))
return user_id # c_longlong(user_id).value
User ID is used as a handle and is passed into other SDK functions. An error is reported and the handle is invalid. Check for negative values. Therefore, it is suspected that there is a type mismatch
Check online I checked it and read the documentation. When calling the C sdk in python, the default return type is int. According to the function definition of the login C version, the return type is LLONG
By default functions are assumed to return the C int
type. Other return types can be specified by setting the restype
attribute of the function object.
Here is a more advanced example, it uses the strchr
function, which expects a string pointer and a char, and returns a pointer to a string:
>>> strchr = libc.strchr >>> strchr("abcdef", ord("d")) 8059983 >>> strchr.restype = c_char_p # c_char_p is a pointer to a string >>> strchr("abcdef", ord("d")) 'def' >>> print strchr("abcdef", ord("x")) None >>>
Set the return value of sdk function to c_longlong, the problem is solved
SDK._dll.CLIENT_Login. restype = c_longlong
After searching online, there are generally two possibilities: The memory is out of bounds or illegal to read or write; another is that the function call stack is too deep.
The code itself adds Condition read-write lock, and buf is also allocated when writing. After repeated debugging, it should not be the problem here. Printing the log shows that it has nothing to do with read and write operations.
Write
index = userdata # c_uint(userdata).value _buf_cond.acquire() # time.sleep(0.2) # 复制图片到内存 # _pic_buf.buf = pBuf c_char 和 c_byte转换 try: temp = [pBuf[i] for i in xrange(0, RevLen)] _buf_list[index].buf = struct.pack('%db' % RevLen, *temp) # 序列号 _buf_list[index].sn = c_ulong(CmdSerial).value _buf_list[index].id = index _buf_list[index].size = c_uint(RevLen).value _buf_list[index].ext = 'jpeg' # encode_dict.get(EncodeType, 'jpeg') except Exception, e: logger.error('截图缓存发生异常:%s' % str(e)) finally: _buf_cond.notify() _buf_cond.release()
读
_buf_cond.acquire()
_buf_cond.wait(timeout=15.0) # 等待200ms再访问数据 # time.sleep(0.2) if _buf_list[self.index].sn == snap.CmdSerial and _buf_list[self.index].id == self.index: self.save_picture(_buf_list[self.index].buf, _buf_list[self.index].ext) self.info('针对通道%d截图成功,IP:%s,Port:%s' % (channel, self.ip, self.port)) pass _buf_cond.release()
After introducing this sdk, a callback function is used. Therefore, the callback function definition level is reduced.
Pass in the function to the base class, and instantiate the function CFUNCTYPE in the base class
Defined in the base class
self.callback = CFUNCTYPE(c_void_p, c_longlong, POINTER(c_byte), c_uint, c_uint, c_ulong, c_ulonglong)
def set_callback(self, save_after_recv_pic, index): self.dll.CLIENT_SetSnapRevCallBack(self._callback(save_after_recv_pic), index)
子类中定义,_save_after_recv_pic也在子类中定义为staticmethod
def _set_callback(self): try: if 0 <= self.index < _buf_size:
self.set_callback(self._save_after_recv_pic, self.index) # 函数调用层次太深,经常报segmentation fault return True else: self.error('设置截图保存回调函数的userdata参数错误:%d' % self.index) return False except Exception, e: self.error('设置截图保存回调函数失败,%s' % str(e)) return False
<br>
Directly instantiate the callback function in the subclass
self.capture_callback = self.callback(self._save_after_recv_pic)
子类中直接注册回调函数
def _set_callback(self): try: if 0 <= self.index < _buf_size: self.dll.CLIENT_SetSnapRevCallBack(self.capture_callback, self.index) # self.set_callback(self._save_after_recv_pic, self.index) # 函数调用层次太深,经常报segmentation fault return True else: self.error('设置截图保存回调函数的userdata参数错误:%d' % self.index) return False except Exception, e: self.error('设置截图保存回调函数失败,%s' % str(e)) return False
The above is the detailed content of The return value when Python calls C SDK does not meet expectations and the solution to Segmentation fault. For more information, please follow other related articles on the PHP Chinese website!