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

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的更多相关文章

  1. Python基本语法_函数_返回值

    目录 目录 前言 函数的返回值 在函数中Return和Print的区别 函数中的文档 前言 函数的返回值是函数重要的组成部分.函数的根本在于实现程序的部分功能,所以很多时候我们需要将函数执行后的结果返 ...

  2. atitit.架构设计---方法调用结果使用异常还是返回值

    atitit.架构设计---方法调用结果使用异常还是返回值 1. 应该返回BOOL类型还是异常 1 2. 最终会有四种状况,抛出异常.返回特殊值.阻塞.超时 1 3. 异常的优缺点点 1 4. jav ...

  3. javascript学习笔记(二):定义函数、调用函数、参数、返回值、局部和全局变量

    定义函数.调用函数.参数.返回值 关键字function定义函数,格式如下: function 函数名(){ 函数体 } 调用函数.参数.返回值的规则和c语言规则类似. <!DOCTYPE ht ...

  4. ASP.NET调用存储过程并接收存储过程返回值

    ASP.NET调用存储过程并接收存储过程返回值 2010-08-02 11:26:17|  分类: C#|字号 订阅       2010年02月27日 星期六 23:52 假设表结构Create T ...

  5. python使用threading获取线程函数返回值的实现方法

    python使用threading获取线程函数返回值的实现方法 这篇文章主要介绍了python使用threading获取线程函数返回值的实现方法,需要的朋友可以参考下 threading用于提供线程相 ...

  6. Python中调用Linux命令并获取返回值

    方法一.使用os模块的system方法:os.system(cmd),其返回值是shell指令运行后返回的状态码,int类型,0表示shell指令成功执行,256/512表示未找到,该方法适用于she ...

  7. Python迭代器:捕获Generator的返回值

    但是用for循环调用generator时,发现拿不到generator的return语句的返回值.如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIteration的v ...

  8. Python基础之函数参数与返回值进阶

    参数作用:如果外界希望在函数内部处理数据,就可以将数据作为参数传入函数内部: 返回值作用:如果希望一个函数函数执行完成后,向外界报告函数的执行结果,就可以使用函数的返回值. 函数的返回值 进阶 利用元 ...

  9. python限定方法参数类型、返回值类型、变量类型等

    typing模块的作用 自python3.5开始,PEP484为python引入了类型注解(type hints) 类型检查,防止运行时出现参数和返回值类型.变量类型不符合. 作为开发文档附加说明,方 ...

随机推荐

  1. Spring mvc4 + ActiveMQ 整合

    一.配置部分 二.代码部分 三.页面部分 四.Controller控制器 五.效果展示 六.加入监听器 七.最最重要的,别忘了打赏 一.配置部分 ActiveMQ的安装这就不说了,很简单, 这个例子采 ...

  2. 程序员的复仇:11行代码如何让Node.js社区鸡飞狗跳

    来源自:http://www.techug.com/node-js-community 几天前,一名 NPM(Node.js Package Manager)社区的贡献者 Azer Koçulu 出于 ...

  3. 二十、【.Net开源】EFW框架核心类库之WebService服务

    回<[开源]EFW框架系列文章索引> EFW框架源代码下载V1.1:http://pan.baidu.com/s/1qWJjo3U EFW框架实例源代码下载:http://pan.baid ...

  4. hdinfo

    --------[ 鲁大师 ]-------------------------------------------------------------------------------- 版本: ...

  5. ruby self.included用法

    ===Module#included 当一个模块混入到类时,如果该模块的included方法已经定义,那么该方法被调用.该方法的唯一参数就是接受混含的类的名字. module M def self.i ...

  6. 我所研究过的 ASP.NET MVC 或者 .NET 或者 ORM 或者框架的开源项目

    ASP.NET MVC 的开源项目有很多,这里列出我所研究过的: SocialGoal v1.0.0 prodinner nopCommerce SmartStore.NET 由于今天才做收集工作,可 ...

  7. ionic 实现自动升级APP

    最近做移动商城开发,需要一个自动升级APP的功能,在网上搜罗很多,发现有的是下载APK,有的在我这服务无法实现,由于时间原因,都被PASS了,最后找到了一个热更新插件,经过半天的调试,可以使用,很欣喜 ...

  8. Tracert 转

    路由跟踪在线Tracert Tracert(跟踪路由)是路由跟踪实用程序,用于确定 IP 数据报访问目标所采取的路径.Tracert 命令用 IP 生存时间 (TTL) 字段和 ICMP 错误消息来确 ...

  9. 专门为码农定制的14款创意的T裇(T-Shirt)设计

    T裇衫是人们在各种场合都可穿着的服装,如在T裇衫上作适当的装饰,即可增添无穷的韵味.通过图案直接反映人类的精神风貌,你可以把日常生活中的兴趣.习惯.喜怒哀乐.嗜好等展露无疑,张扬个性.秀出自我.对于码 ...

  10. iOS-微信-分享

    一.微信原生的分享--准备工作. 1. 需要申请微信AppId. 2. 导入系统架包. SDK文件包括 libWeChatSDK.a,WXApi.h,WXApiObject.h,WechatAuthS ...