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

Posted

技术标签:

【中文标题】在 VB6 应用程序中使用 C++ DLL【英文标题】:Using C++ DLL in VB6 app 【发布时间】:2015-02-18 17:03:28 【问题描述】:

我正在关注以下指南: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") failed - 找不到指定的模块。

如何解决?


更新: 我已经进一步研究了这个问题,请参阅“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 应用程序中创建定义文件 (.def) 来完成的名称

在新的 Source.def 文件中,我定义了我想要“添加”功能:

     LIBRARY 

     EXPORTS
        Add

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

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

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

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

之后,dumpbin.exe 返回了更好的值:

     1    3 00001050 Add

但这并没有完全解决我的问题,我仍然会得到“错误的 DLL 调用约定”,这是由于我在 VB6 中引用库的方式

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

函数“Add”返回一个双精度值,在上面的声明中我声明值应该被推送并且没有给出返回值。所以我遵循了我在 C++ 中的函数格式,并添加了一个与 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!

【问题讨论】:

我使用了“Dependency Walker”程序,发现我缺少MSVCR120D.DLL 如果您仍有问题***.com/questions/14281368/…,此问题中的建议及其接受的答案可能会很有用 【参考方案1】:

你所做的有几点是错误的。有趣的是,尽管如此,它应该可以工作。

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

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

resvr32 需要特殊的导出函数来 COM Conform 在注册表中注册 DLL。一个支持 COM 的 DLL 可以通过例如 for 来使用。与 CoCreateInstance 不与您的声明。

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

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

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

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

正如有人已经建议的那样,使用依赖步行者。如果缺少以“MS”开头的 dll。阅读我的以下答案:

https://***.com/a/18600033/1922748

安装正确的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,在你的情况下你不需要它。

【讨论】:

好的,我会试试的。我需要转换在 Visual 2010 中创建的 C++ 应用程序,所以希望如果这可行,我将能够从我需要处理的 C++ 应用程序编译一个 dll。 现在说系统“找不到DLL入口点Add in Win32Project1.dll” 我已经进一步研究了它,它恰好是 VC++ 对 DLL 函数进行编码,因此我会有一个有趣的函数名称。 那叫装饰。将您的函数放在 extern "C" 之间 我设法让它运行,现在我需要将 C++ 应用程序转换为 C++ DLL,这个应用程序还运行 MFC...我希望尝试并复制在虚拟 DLL 中所做的事情并通过 VB6 触发 C++ DLL 中的一个函数,然后转换其他 3 个函数以通过 DLL 使用。感谢您的帮助:)

以上是关于在 VB6 应用程序中使用 C++ DLL的主要内容,如果未能解决你的问题,请参考以下文章

找不到从 VB6 调用的 C++ DLL 程序

如何在不通过 COM 的情况下从 VB6 调用 C++ DLL?

从 VB6 访问 C++ DLL 中的位图资源

是否可以同时调试 VB6 和 C++ COM dll?

试图在 VB6 的 C++ DLL 中显示 UI 会导致在 AfxGetResourceHandle 处断言

从 64 位应用程序加载/与 vb6 COM dll 交互