1. 程式人生 > >如何使用Python呼叫dll動態連結庫?

如何使用Python呼叫dll動態連結庫?

1. 需求

最近有這樣一個需求:網路上下載了大佬的深度學習影象識別模型,想要整合到自己的後端作為服務呼叫。
模型是.dll檔案,而我這邊使用的是Python。

2. 思路

.dll是使用C或者C++編譯的動態連結庫,一般留有函式入口可以進行呼叫。
首先我們通過閱讀原專案的原始碼,找到入口的函式名稱、傳參規則和型別、返回值型別。
然後使用Python ctype庫載入dll庫,並且呼叫函式,得到返回值。

3. 讀原專案原始碼

我們發現原專案中可以這樣呼叫

recognize(content=>bytes, len(content)=>int)
return "1234"=>str

這意味著,我們在python中呼叫的時候可以把recognize這個函式作為入口。

4. ctype

網路上ctype的資料很多,這裡不多說,直接上程式碼和註釋。

from ctypes import *

dll = windll.LoadLibrary("ocr.dll")  # 載入連結庫
ocr = dll.ocr  # 把function賦值
ocr.argtypes = [c_char_p, c_int]  # 指定傳入引數的型別,這裡的c_char_p和c_int分別代表二進位制型別和整型
ocr.restype = c_char_p  # 指定返回值型別(這裡有個坑,如果返回得不到你想要的結果,可以分別嘗試c_char_p和c_wchar_p)
with open("./test.jpg", "rb") as f:
    content = f.read()
# 這裡開啟一張圖片來構造一個二進位制資料
r = dll.ocr(content, len(content))  # 按照指定型別傳入資料
print(r)  # 得到返回值
print(r.decode("utf-8"))

這裡注意:如果ocr這個函式返回二進位制型別但是選擇字串型別作為返回值,程式會自動幫你解碼,但是解碼結果存在問題。所以這裡最好把返回值型別指定為二進位制!

5. 過程中遇到的錯誤

5.1 OSError: [WinError 193] %1 不是有效的 Win32 應用程式

說明dll檔案只支援32位呼叫,你可以安裝一個32位的python使用。

5.2 Procedure called with not enough arguments (4 bytes missing) or wrong calling convention error occuring when trying to call a function of a ctype DLL

  1. dll = cdll.LoadLibrary(“ocr.dll”)
  2. dll = windll.LoadLibrary(“ocr.dll”)
    如果報錯可以試一下另外一種載入方式

參考:https://stackoverflow.com/questions/26201751/procedure-called-with-not-enough-arguments-4-bytes-missing-or-wrong-calling-co

dll反編譯:https://www.jb51.net/softs/629352.html
官方文件:https://docs.python.org/3.5/library/ctypes.html#
參考1:https://blog.csdn.net/awakeljw/article/details/79369703
參考2:https://www.cnblogs.com/night-ride-depart/p/4907613.html