首頁  >  文章  >  後端開發  >  Python呼叫C的SDK出現回傳值不符合預期以及Segmentation fault的解決方法

Python呼叫C的SDK出現回傳值不符合預期以及Segmentation fault的解決方法

高洛峰
高洛峰原創
2017-03-20 11:04:101869瀏覽

1、sdk回傳值不是int型

1.1 登入函數呼叫

def login(ip, port, username, password, device_info, error_code):
"""
LLONG CLIENT_Login(
char *pchDVRIP, WORD wDVRPort,
char *pchUserName, char *pchPassword,
LPNET_DEVICEINFO intDredeviceInfoFO intDDlp* = 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

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

#4開始#1.2 無效的ID

用戶ID作為句柄,傳入其他SDK函數中,報錯,句柄無效。查看出現負值。因此懷疑是類型不符

 

1.3 設定回傳類型

1.3.1 錯誤原因

網路上查了下,並看了下文檔,

python

中調用C的sdk,預設返回的是int型,按照login C版本的函數定義,返回的是LLONG型

15.17. 1.8. Return types

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
>>>
###1.3.2 修改######設定sdk###函數的回傳值###為c_longlong,問題解決######SDK._dll.CLIENT_Login. restype = c_longlong###### ######2、###回呼函數###場景下大概率出現Segmentation fault######網路找了一圈,一般兩種可能性:記憶體越界或讀寫非法; 還有一種就是函數呼叫棧太深。 ######2.1 讀寫加鎖######程式碼本身就加入了Condition讀寫鎖得,buf也是在寫的時候分配的,多番調試,應該不是這個地方因為的問題。列印日誌看,也與讀寫操作無關。 ######寫入###
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()
### ######2.2 減少堆疊呼叫層次######由於引入這個sdk之後,使用了回呼函數。因此將回呼函數定義層次減少。 ######2.2.1 修改前######傳入函數給基底類,在基底類別中CFUNCTYPE實例化函數###### ######基底類別中定義## #
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
 
###2.2.2 修改後問題解決######子類別中直接實例化回呼函數###
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

以上是Python呼叫C的SDK出現回傳值不符合預期以及Segmentation fault的解決方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn