如何加载Python生成的DLL到VB.NET 解决0x8007007E加载报错
问题描述
通过Python生成包含求和、求差简单函数的自定义DLL,在VB应用程序中调用相关函数时程序无法正常运行,实现代码如下:
Module testfunc Public Declare Function do_sum Lib “testfunc.dll” (ByVal a As Integer, ByVal b As Integer) As Integer Public Declare Function do_diff Lib “testfunc.lib” (ByVal a As Integer, ByVal b As Integer) As Integer End Module Module Program Sub Main(args As String()) Console.WriteLine("Hello World!") Dim result As Double, result2 As Integer result = do_sum(12, 34) Console.WriteLine("sum = {0}", result) result2 = do_diff(129, 34) Console.WriteLine("diff = {0}", result2) End Sub End Module
已将DLL和LIB文件均放置在BIN目录下,运行代码时立即触发报错:
Unable to load DLL 'testfunc.dll' or one of its dependencies: The specified module could not be found. (0x8007007E)
已尝试的无效方案
- 使用regsvr32注册该DLL,未生效
- 将DLL作为依赖项资源添加到项目,仍无法运行
- 配置DLL的完整绝对路径,依旧出现上述相同报错
问题根因
- P/Invoke声明存在低级错误:
do_diff函数的Lib参数指向了testfunc.lib,.lib是C/C++编译链接阶段使用的静态导入库,VB运行时不会加载这类文件,该声明从一开始就是错误的。另外do_sum返回值声明为Integer,但接收返回值的变量定义为Double,会导致后续返回值读取异常。 - regsvr32注册操作完全无效:regsvr32仅能注册符合COM组件规范的DLL,Python生成的原生函数DLL不属于COM组件,不需要也无法通过该工具注册,该操作对解决问题没有任何帮助。
- 平台位数不匹配:如果生成DLL使用的Python是32位,而VB项目目标平台设置为64位,或反之,系统会直接抛出找不到模块的错误,和DLL本身路径是否正确无关。
- DLL依赖缺失:0x8007007E报错90%以上的场景不是目标DLL找不到,而是目标DLL依赖的其他运行时库不在搜索路径中。Python生成的DLL默认依赖Python核心运行时(如
python3x.dll)、VC++运行时库(如vcruntime140.dll),如果编译时没有静态打包这些依赖,系统找不到依赖项时就会抛出和找不到目标DLL完全一致的错误,这也是配置了绝对路径依然报错的核心原因。
解决步骤
按以下顺序操作即可解决问题:
- 修正P/Invoke声明错误:将
do_diff的Lib参数修改为testfunc.dll,同时统一返回值变量类型,修正后的代码参考:
运行时不需要Module testfunc Public Declare Function do_sum Lib "testfunc.dll" (ByVal a As Integer, ByVal b As Integer) As Integer Public Declare Function do_diff Lib "testfunc.dll" (ByVal a As Integer, ByVal b As Integer) As Integer End Module Module Program Sub Main(args As String()) Console.WriteLine("Hello World!") Dim result As Integer, result2 As Integer result = do_sum(12, 34) Console.WriteLine("sum = {0}", result) result2 = do_diff(129, 34) Console.WriteLine("diff = {0}", result2) End Sub End Module.lib文件,可以直接从BIN目录删除。 - 统一平台目标位数:打开VB项目属性-生成页,将目标平台设置为和生成DLL所用Python一致的位数:Python为64位就选x64,32位就选x86,不要使用「Any CPU」选项避免自动适配位数出错。
- 补全DLL依赖项:如果是用Cython/Nuitka编译DLL,编译时加上
--standalone参数即可自动打包所有依赖,直接把输出目录下的所有DLL拷贝到VB项目BIN目录即可。如果是手动编译的DLL,可以通过VS自带的dumpbin /dependents testfunc.dll命令查看所有依赖项,把列出的非系统核心DLL(Python运行时、VC++运行时等)全部和testfunc.dll放在同一目录。 - 配置自动复制规则:不要手动往BIN目录拷贝文件,直接把testfunc.dll和所有依赖DLL添加到VB项目中,在文件属性页将「复制到输出目录」设置为「如果较新则复制」,避免编译运行时文件拷贝不全。
- 匹配调用约定:如果Python函数是用Cdecl约定导出的,需要在VB函数声明中加上
CallingConvention:=CallingConvention.Cdecl参数,避免加载成功后出现栈不平衡错误。
内容的提问来源于stack exchange,提问作者Amit Jain
相关产品推荐
相关产品推荐

