一、项目说明

        工作中遇到项目中需要将一些 C/C++算法封装为 dll 文件给 Python 调用,做到算法保密。算法的封装网上教程比较多,可以多多参考这篇文章,或者别的文章都可以。

二、Python 调用 dll

        因为我的C++算法没有涉及很复杂的 class,也没有将对象以自定义class的方式来做返回,所用的都是返回基本的数据类型,如字符串、整型数字、浮点数字等,如果你需要返回C++的自定义对象的话,可能要考虑别的方案了,本篇文章不做介绍,据说好像可以用 SWIG,不过具体的我也不太清楚,如有有教程的话,还请在评论区告知我~

        本篇 Python 采用的是 ctypes 来作为调用 dll 的库。ctypes 主要是能够满足 C 代码的调用。如通过结构体传参,返回结构体来接收,C 中基本的数据类型的传参和接收。我主要从这个链接中学到 ctypes 的用法,以及这篇文章学到python中结构体传参。

三、遇到的坑

        我开发时是现在 vs2017 中编译好 dll,并生成了测试算法用的 exe 程序(这个很重要)。再将编译好的 dll 放到了 pycharm 的项目中, ctypes 调用 dll 的 api 也是很容易就搜得到,如

import ctypes
from ctypes import *

# 写法1
dll = CDLL("test.dll")
# 写法2
dll = ctypes.cdll.LoadLibrary("test.dll")
# 两种写法貌似是一样的,没有深究,有了解的同学可以在评论区中说一下

test.dll 的路径就和这个 py 文件同级目录。可问题就出在这个地方,在本电脑运行🆗,但是在交付代码时(在别的电脑上)就报错,FileNotFoundError: Could not find module 'test.dll'。开发时电脑的 python 是 3.7,而交付电脑 python 版本是 3.9,而在网上看到这样一篇文章,说是 python 3.8 调用的时候有点问题,解决方案有三,具体看链接中文章尾处。可我通过 os 库获取运行路径定位到 test.dll,仍然报 FileNotFoundError: Could not find module 'xxx/xxxx/test.dll' 这样的错;然后又根据文章尝试 add_dll_directory 这个 api,可以仍然报这个错。

接下来我就想,python 这边都用上绝对路径都不行了,是不是系统环境对C代码支持的问题呢?

我尝试把之前编译好的用于测试的exe文件移植到交付电脑上运行,报错:the code execution cannot proceed because msvcp140d.dll was not found....,the code execution cannot proceed because ucrtbased.dll was not found....,the code execution cannot proceed because vcruntime140d.dll was not found....,这三个弹窗都提示缺少对应的 dll,我忽然觉得可能发现突破口了!

我果断将我电脑上的三个dll复制过去(复制到C:\Windows\System32中)。再来运行 py 代码,居然发现运行成功了!不需要什么 add_dll_directory或者绝对路径什么的。所以网上的做法也不能全信啊,哈哈。

之后我看了网上的各种相关问题,好像没人说 add_dll_directory 有什么问题,关于这个 api 底层是怎么回事,还未可知。为什么我使用 add_dll_directory 没有反应,但是加上缺少的 dll 后就可以运行了。python 的报错指向的是 not found,理论上来说更应该是报 dll 程序的错误才对吧?毕竟 dll 的运行环境需要一些系统的 dll。有对这方面有了解的同学也请在评论区告知一下。


Talk is cheap, show me the code —— 薪火工作室箴言

散是满天星,聚是兴薪之火。

更多推荐

Python 调用 C/C++ dll 的方法以及遇到的坑