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
- dll = cdll.LoadLibrary(“ocr.dll”)
- 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