Python調用C的SDK出現返回值不符合預期以及Segmentation fault

来源:http://www.cnblogs.com/inns/archive/2016/12/21/6209504.html
-Advertisement-
Play Games

1、sdk返回值不是int型 1.1 登錄函數調用 def login(ip, port, username, password, device_info, error_code):"""LLONG CLIENT_Login(char *pchDVRIP, WORD wDVRPort,char *p... ...


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函數中,報錯,句柄無效。查看出現負值。因此懷疑是類型不匹配

image

 

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

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在多線程(線程同步)中,我們將學習多線程中操作共用資源的技術,學習到的知識點如下所示: 執行基本的原子操作 使用Mutex構造 使用SemaphoreSlim構造 使用AutoResetEvent構造 使用ManualResetEventSlim構造 使用CountDownEvent構造 使用Bar ...
  • 目錄 前言 OAuth2.0簡介 授權模式 (SimpleSSO示例) 使用Microsoft.Owin.Security.SimpleSSO模擬OpenID認證 通過authorization code授權模式申請令牌 通過implicit授權模式申請令牌 通過password模式申請令牌 通過c ...
  • 你真的懂異常(Exception)嗎? 目錄 異常介紹 異常的特點 怎樣使用異常 處理異常的 try-catch-finally 捕獲異常的 Catch 塊 釋放資源的 Finally 塊 捕獲異常的 Catch 塊 釋放資源的 Finally 塊 一、異常介紹 我們平時在寫程式時,無意中(或技術不 ...
  • 隨著公司業務的發展,網站的日活數也逐漸增多,以前只需要考慮將所需要的功能實現就行了,當日活越來越大的時候,就需要考慮對伺服器的資源使用消耗情況有一個清楚的認知。 最近老是發現資料庫的連接數如果幾天不重啟伺服器,就經常會發現有很多sleep很久的資料庫連接,對資料庫伺服器的性能有較大的影響。所以需要知 ...
  • 一.簡介 在網頁應用中,你經常需要在處理完表單或其它類型的用戶輸入後,顯示一個通知消息(也叫做“flash message”)給用戶 對於這個功能,Django 提供基於Cookie 和會話的消息,無論是匿名用戶還是認證的用戶。 其消息框架允許你臨時將消息存儲在請求中,併在接下來的請求(通常就是下一 ...
  • 線程可以理解為下載的通道,一個線程就是一個文件的下載通道,多線程也就是同時開啟好幾個下載通道。當伺服器提供下載服務時,使用下載者是共用帶寬的,在優先順序相同的情況下,總伺服器會對總下載線程進行平均分配。不難理解,如果你線程多的話,那下載的越快。 現流行的下載軟體都支持多線程,且支持中途暫停下載,再次開 ...
  • 如果運行後如圖的錯,需要進行如下操作來解決: a:打開cmd,輸入netstat -ano 找到本地地址為8080的最後一項的數字,這個數字就是埠號。 b:再輸入taskkill /t /pid 埠號數字 /f 來關閉此進程。 c:註意每個命令後面不要加 ; 結尾,運行以上命令再重新運行工程即可 ...
  • 本文地址 可以拜讀: 從零開始學 Java 分享提綱: 1.java數據結構 1. java數據結構 1)【概述】 Java工具包提供了強大的數據結構。在Java中的數據結構主要包括以下幾種介面和類: 枚舉(Enumeration) 位集合(BitSet) 向量(Vector) 棧(Stack) 字 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...