>  기사  >  백엔드 개발  >  Python이 C SDK를 호출할 때 반환 값이 기대치를 충족하지 못하며 분할 오류에 대한 솔루션

Python이 C SDK를 호출할 때 반환 값이 기대치를 충족하지 못하며 분할 오류에 대한 솔루션

高洛峰
高洛峰원래의
2017-03-20 11:04:102013검색

1、sdk返回值不是int型

1.1 登录函数调用

def 로그인(ip, 포트, 사용자 이름, 비밀번호, device_info, error_code):
"""
LLONG CLIENT_Login(
char *pchDVRIP, WORD wDVRPort,
char *pchUserName, char *pchPassword,
LPNET_DEVICEINFO lpDeviceInfo, int *error = 0);
:param ip:
:param 포트:
:param 사용자 이름:
:param 비밀번호:
:param device_info:
:param 오류_코드:
:반환: LLONG
"""
ip_buffer = c_buffer(ip)
# ip_buffer.encode('utf8')
# user_id = c_longlong(0)
user_id = SDK._dll.CLIENT_Login( byref(ip_buffer), 포트, 사용자 이름, 비밀번호, byref(device_info), byref(error_code))
return user_id # c_longlong(user_id).value

1.2 无效적 ID

사용 가능한 ID가 생성되었습니다.不匹配

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

 

1.3 设置返回类型

1.3.1 错误原因

网上查了下,并看了下文档,python중 C의 SDK, 默认返回的是int型, 按Photologin C版本的函数定义, 返回的是LLONG型

15.17.1.8. 반환 유형

기본적으로 함수는 C int 유형을 반환하는 것으로 가정됩니다. restypeobject 함수의 속성을 ​​설정하여 다른 반환 유형을 지정할 수 있습니다.

여기에 더 고급 예제가 있는데, strchr 함수를 사용합니다. >string 포인터와 char을 사용하고 문자열에 대한 포인터를 반환합니다.

>>> 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、

回调函数场景下大概率出现세그먼트 오류

网上找了一圈,一般两种可能性:内存越界或者读写不法; 还有一种就是函数调用栈太深。

2.1 读写加锁

代码本身조건이 매우 좋지 않습니다.操作无关。

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
 <br>
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를 호출할 때 반환 값이 기대치를 충족하지 못하며 분할 오류에 대한 솔루션의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.