【问题标题】:Creating DLLs in C++在 C++ 中创建 DLL
【发布时间】:2011-02-14 14:16:30
【问题描述】:

这是this question 的后续问题,因为我现在正在为此失去理智。

有人将我指向this article,我正试图从那里复制第 4 节。

所以我在 MSVC++2010 中创建了一个空的 C++ 项目,在其中创建了一个新的 .cpp 文件,并将以下代码放入其中:

#include <windows.h>
#define CCONV _declspec(dllexport) // used to be __stdcall but resulting DLL is identical

int CALLBACK LibMain (HANDLE hInstance, WORD wDataSeg, WORD wHeapSize,
LPSTR lpszCmdLine)
{
     return 1;
}

short CCONV PassInteger (short intgr, short far *pintgr)
{
    *pintgr = intgr;
    return intgr + 1;
}

(我从here 获得了LibMain 代码,但我认为它在这里没有任何作用。)

然后,我在项目中添加了一个 .def 文件并将其放入其中:

;vb6dll32 DEF File
LIBRARY vb6dll32

CODE PRELOAD MOVEABLE DISCARDABLE
DATA PRELOAD MOVEABLE

EXPORTS
PassInteger

编译器会输出两个警告,即当前目标不支持 .def 文件中的 CODEDATA,但它最终会编译并生成文件 vb6dll32.dll,然后我将其复制到 C:\windows\system...\system32C:\

然后我创建了一个 VB6 项目,在表单中放了一个按钮并添加了这个源代码:

Private Declare Function PassInteger Lib "vb6dll32.dll" _
(ByVal intgr As Integer, pintgr As Integer) As Integer

Private Function BuiltIntest() As Integer

    Dim i As Integer
    Dim ir As Integer

    i = 7

    i = PassInteger(i, ir)
    Print i, ir

    Return

End Function

Private Sub Command1_Click()
    MsgBox (BuiltIntest())
End Sub

现在,当我单击按钮时,它仍然给我“运行时错误'53':找不到文件 vb6dll32.dll。” (即使我在 VB 源代码中给它一个完全指定的路径,也会发生这种情况,例如“C:\vb6dll32.dll”并且文件肯定在那里。我尝试在没有路径和没有“.dll”的情况下给出它的位置等等,没有任何变化。)

让我烦恼的是,当我运行regsvr32 c:\vb6dll32.dll 时,它还告诉我“模块 C:\vb6dll32.dll 无法加载。等等等等”.. 我不知道它应该做什么,但通常应该这样为 DLL 文件做点什么,对吧?

我做错了什么?!感谢您的帮助。

【问题讨论】:

    标签: c++ dll vb6 dllexport


    【解决方案1】:

    在您的示例(代码和 regsvr32 调用)中,您指的是c:\vb6dll32.dll。但是你说你把它复制到了system32目录。您指定的路径要求它位于根目录中。由于您将其复制到 system32 目录,因此它应该可以在没有任何路径的情况下工作。尝试从名称中删除 c:\

    编辑由于我在各个方面都在罢工,您可能会犹豫是否听从我的建议……但Dependency Walker 可能有助于解决这个问题。可能是找不到您的 DLL 所需的 DLL(例如,CRT DLL 之一)。这个depends.exe 实用程序是一个非常有用的工具,它会显示是否缺少任何必要的DLL。

    【讨论】:

    • 没关系。我尝试了没有路径,没有“.dll”,有路径,将其复制到“C:\”,尝试了该路径......没有任何变化。
    • 鉴于错误消息,我不确定这是否适用,但您可以尝试运行命令 dumpbin /exports vb6dll32.dll。如果它是一个有效的 DLL,那么您应该会看到导出的符号。 dumpbin.exe 命令应位于 Visual Studio 安装下的 vc\bin 目录中。还应该有一个名为 vcvars32.bat 之类的批处理文件,它将设置您的路径变量以访问该实用程序。
    • 这看起来很可疑,听起来好像是 Visual Studio 安装有问题。不过,我真的不知道这是否与无法加载 DLL 直接相关。
    • 非常感谢。 Dumpbin 找到了导出并列出了所有导出的函数——据我所知,这是正确的。 (抱歉之前的帖子,我忘了先用vcvars32准备控制台。)
    • @Felix:没问题。我添加了一个关于depends.exe 的注释,您可能会查看(如果您想继续遵循我的建议,但还没有帮助:)
    【解决方案2】:

    也许你的 vb6dll32.dll 是动态链接的,并且依赖于 MSVCR100.dll 之类的东西,它 不容易找到。检查导入并将这些 dll 放在您的 vb6dll32.dll 旁边,或者 静态链接(/MT /LD)。
    此外,您真的不需要 .def 文件中的这些 CODE 和 DATA 行。

    【讨论】:

    • 其实你说的很对。我使用了 Mark 提出的 Dependency Walker,它说我的 DLL 依赖于另外两个东西:KERNEL32.DLL 和 MSVCR100.DLL,但没有找到。我该如何解决这个问题?
    • 在您的 c++ 项目属性中使用 (/MT) 而不是 (/MD) 链接转到“配置属性 > C/C++ > 代码生成 > 运行时库”。这将静态包含 MSVCR100,这将使您的 DLL 更大,但您不必担心依赖关系
    【解决方案3】:

    LibMain 来自 16 位窗口。您应该使用 DllMain。 http://msdn.microsoft.com/en-us/library/ms682583(v=vs.85).aspx。您可以查看 fdwReason 与 DLL_PROCESS_ATTACH 和 DLL_PROCESS_DETACH 用于使用 LoadLibrary 加载和卸载 dll 时。您可以在 DllMain 中使用的内容有一些规定,例如不能使用非托管代码。

    【讨论】:

    • 我不能在 DllMain 中使用非托管代码?应该是反过来吧?
    • @Felix Dombek:你是对的,我的意思是管理。原因是你不能在 DllMain 中调用 LoadLibrary(看看 msdn 文章的一半多一点)。由于托管代码可能随时加载外部库,因此您无法进行托管调用。如果您已经知道这一点,我深表歉意,但这可能有助于解决相关问题。
    • 不,我不知道,谢谢。但是,我不打算在这里使用托管代码。我只想有一个带有导出的 C++ DLL 的最小测试用例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-26
    • 2011-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多