The return value when Python calls C SDK does not meet expectations and the solution to Segmentation fault

高洛峰
Release: 2017-03-20 11:04:10
Original
1948 people have browsed it

1. The sdk return value is not int type

1.1 LoginFunctionCall

deflogin(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);
:paramip:
:paramport:
:paramusername:
:parampassword:
:paramdevice_info:
:paramerror_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))
returnuser_id# c_longlong(user_id).value

1.2 Invalid ID

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

Python调用C的SDK出现返回值不符合预期以及Segmentation fault的解决方法

1.3 Set the return type

1.3.1 Error cause

Check online I checked it and read the documentation. When calling the C sdk inpython, the default return type is int. According to the function definition of the login C version, the return type is LLONG

15.17. 1.8. Return types

By default functions are assumed to return the Cinttype. Other return types can be specified by setting therestypeattribute of the functionobject.

Here is a more advanced example, it uses thestrchrfunction, which expects astringpointer 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 >>>
Copy after login

1.3.2 Modify

Set the return value of sdkfunctionto c_longlong, the problem is solved

SDK._dll.CLIENT_Login. restype = c_longlong

2,Callback functionSegmentation fault is likely to occur in this scenario

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.

2.1 Read-write lock

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()
Copy after login
Copy after login
_buf_cond.acquire()
Copy after login
_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()
Copy after login

2.2 Reduce stack call level

After introducing this sdk, a callback function is used. Therefore, the callback function definition level is reduced.

2.2.1 Before modification

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)
Copy after login
def set_callback(self, save_after_recv_pic, index): self.dll.CLIENT_SetSnapRevCallBack(self._callback(save_after_recv_pic), index)
Copy after login
子类中定义,_save_after_recv_pic也在子类中定义为staticmethod
Copy after login
def _set_callback(self): try: if 0 <= self.index < _buf_size:
Copy after login
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
Copy after login

Copy after login

2.2.2 Problem solved after modification

Directly instantiate the callback function in the subclass

self.capture_callback = self.callback(self._save_after_recv_pic)
Copy after login
子类中直接注册回调函数
Copy after login
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
Copy after login

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!

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!