在 VB6 应用程序中使用 C++ DLL

Using C++ DLL in VB6 app

我正在遵循以下指南:https://msdn.microsoft.com/en-us/library/ms235636.aspx

我已经创建了一个如上所述的 DLL,现在我想将它包含在我的 VB6 应用程序中

我在代码中声明了一个函数:

Private Declare Function Add Lib "C:\WINDOWS\system32\Win32Project1.dll" (ByVal a As Double, ByVal b As Double)

在表单加载中我声明了一些变量并调用了一个函数

Dim a As Double
Dim b As Integer

a = 7.4
b = 99

Call Add(a, b)

每次我 运行 程序时,我都会收到找不到文件的错误。 文件存在于 C:\WINDOWS\system32\ 中,我确实尝试使用以下方式注册 dll:

regsvr32 Win32Project1.dll

但我不断收到错误消息: LoadLibrary("Win32Project1.dll") 失败 - 找不到指定的模块。

如何解决?


更新: 我进一步研究了这个问题,请参考 "Martin Schlott" 答案的第 2 步,碰巧 VC++ 编码 DLL 函数,因此我会在 DLL 中有一个有趣的函数名称.

使用可以在 $\Visual Studio\VC\bin 中找到的 dumpbin.exe,我能够读取存储在 DLL 中的函数名称。这是我最初会得到的:

      1    0 00001050 ?Add@MyMathFuncs@MathFuncs@@SANNN@Z = ?Add@MyMathFuncs

@MathFuncs@@SANNN@Z (public: static double __cdecl MathFuncs::MyMathFuncs::Add(d 双,双))

"?Add@MyMathFuncs@MathFuncs@@SANNN@Z" - 是我必须在 VB6 中作为函数调用才能正常工作的东西......它不会......所以我不得不通过在 C++ DLL app

中创建定义文件 (.def) 来解码名称

在新的 Source.def 文件中,我定义了我想要 "Add" 函数:

     LIBRARY 

     EXPORTS
        Add

在 "Release" 模式下重建解决方案后 dumpbin 给了我更好的结果。但是,__cdecl 会自动添加到 VC++ 中的每个函数,除非另有说明,而且碰巧 __cdecl 不允许在 VB6 中使用函数。如果您现在 运行 VB6 应用程序,您将收到一个新错误 "Bad DLL calling convention"。

为了解决这个问题,我必须修改 "MyMathFuncs.h" 文件,我在其中定义了要导出和更改的函数

     "static MATHFUNCSDLL_API double Add(double a, double b);"

     "static MATHFUNCSDLL_API double __stdcall Add(double a, double b);"

在那之后 dumpbin.exe returned 更好的值:

     1    3 00001050 Add

但这并没有完全解决我的问题,我仍然会得到 "Bad DLL calling convention",这是由于我在 VB6

中引用库的方式
     Private Declare Function Add Lib "Win32Project1.dll" (ByVal a As Double, ByVal b As Double)

函数 "Add" return 是一个双精度函数,在上面的声明中我声明值应该被压入并且没有给出 return 。所以我遵循了 C++ 中的函数格式,并添加了一个 return,其数据类型与 C++ 文件中的数据类型相匹配:

     Private Declare Function Add Lib "Win32Project1.dll" (ByVal a As Double, ByVal b As Double) As Double

现在当我运行:

Dim a As Double
Dim b As Integer

a = 7.4
b = 99

MsgBox (Add(a, b))

我有一个消息框说结果是 106.4!

你的做法有几点不对。有趣的是,尽管如此它应该工作。

如果直接指定DLL,则不需要用regsvr32注册。

阅读: https://msdn.microsoft.com/en-us/library/aa716201(v=vs.60).aspx

resvr32 期望特殊导出函数以 COM 符合在注册表中注册 DLL。 COM able DLL 可以用于例如使用 CoCreateInstance 而不是使用您的声明。

如果您不知道这一点,regsvr 会失败。

也不要将属于您的项目的 DLL 复制到 system32 文件夹中。它不属于那里,现在是不良行为。出于磁盘内存的原因,它在几个世纪前可能是必需的,但现在不是。

将 DLL 复制到 VB 程序所在的同一文件夹中。将路径更正为

Private Declare Function Add Lib "Win32Project1.dll" (ByVal a As Double, ByVal b As Double)

并且正如有人已经建议的那样,使用 dependency walker。如果缺少以 "MS" 开头的 dll。阅读我的以下回答:

安装正确的 redist。

更新

您写道您缺少 "MSVCR120D.DLL"。如果您在调试模式而非发布模式下编译 DLL,就会发生这种情况。如果没有 Visual Studio,则无法安装 MSVCR120D.DLL。您需要在发布模式下编译您的 DLL 并安装 redist。

2。第二次更新

关于您最后的评论,缺少入口点。 你必须导出函数!添加

__declspec(dllexport) 

在您要导出的函数之前。看这里 https://msdn.microsoft.com/de-de/library/3y1sfaz2.aspx

您在 C++ 中的声明应如下所示:

__declspec(dllexport) double Add(double val);

您可以忘记 dllimport,在您的情况下不需要它。