【问题标题】:How to dllimport in Microsoft Visual C++如何在 Microsoft Visual C++ 中导入 dll
【发布时间】:2011-05-01 18:24:28
【问题描述】:

我有一个 DLL,我想使用它的一些功能。

#include <iostream>

using namespace std;

extern "C" __declspec(dllimport) int Initialize(char* localPort, char* adminServerName, int rpcTimeout);


int main()
{
    int res = Initialize("7864", "6000@kabc", 10000);

    return 0;
}

我没有 DLL 的 .lib 文件,所以无论如何我可以链接到它。我想到的一件事是使用 LoadLibrary 函数,然后使用 GetProcAddress()。有没有其他办法?

当我编译以下代码时

  • 错误 LNK2019:未解析的外部符号 _imp_Initialize 在函数 _main

  • 中引用
  • 致命错误 LNK1120:1 个未解决的外部问题

我收到上述错误

我使用的是 Windows 和 Visual Studio 2008

【问题讨论】:

  • 您没有随 DLL 一起提供的相应头文件吗?
  • 因为这取决于系统和编译器,请告诉我们您的系统和编译器(它可能对潜在的回答者有用)
  • 好吧,您需要猜测确切的函数签名(假设您做对了),并在项目设置中将 DLL 指定为依赖项(假设您使用的是 Visual Studio)。这应该会有所帮助。
  • Import a DLL with C++ (Win32) 的可能重复项

标签: c++ linker linker-errors dllimport visual-c++


【解决方案1】:

在visual studio下不能直接链接DLL,需要导入库。

所以基本上你有几个选择:

  1. 创建导入库表单 dll 并链接到它。 MinGW 附带了一些工具可以完成这项工作,它们实际上可能对你有用,AFAIK 还有一些用于 MSVC 的工具。

    这可能会有所帮助:http://support.microsoft.com/kb/131313,我自己没有测试过

  2. 使用 GetProcAddress
  3. 使用 gcc,因为它知道直接与 DLL 链接而无需导入库 :-)

【讨论】:

    【解决方案2】:

    从您的措辞可以看出您正在使用 Dev Studio 的某个或其他版本。

    为了隐式链接到一个 dll,VC++需要一个 .lib 文件,没有问题。如果没有 .lib,您只能使用 LoadLibrary 和 GetProcAddress 显式加载 dll。

    幸运的是,导入库只包含 dll 的导出符号,因此在 VC++ 中简单地创建一个导出相同符号的 dll 项目,构建它,然后使用生成的 .lib 文件访问目标 dll 是完全合法的.

    真正的诀窍是,正确使用符号:根据原始 dll 的创建方式,可能需要处理一些装饰。

    当使用dependencywalker查看时,可以通过多种方式从 dll 中导出“初始化”

    • “初始化” - 通过 .DEF 文件或通过 extern "C" __declspec(dllexport) int __cdecl Initialize(... 导出
    • "_Initalize@16" - 导出使用:extern "C" __declspec(dllexport) int __stdcall Initialize(...
    • ?Initialize@@YAHPADOH@Z" - `__declspec(dllexport) int Initialize(char*,char*,int);
    • ?Initialize@@YGHPADOH@Z" - `__declspec(dllexport) int __stdcall Initialize(char*,char*,int);

    问题确实是第一种情况 - 如果调用约定不是 __cdecl(并且大多数 dll api 实际上是 __stdcall - 所有 Windows dll 都是 __stdcall),那么您必须使用 .def 文件来导出未修饰的名称。

    【讨论】:

    • 我必须导出所有符号还是只导出我想使用的符号?
    • @Tux:自然只有你需要使用的那些
    【解决方案3】:

    一个好方法是重建一些头文件,以声明您要调用的函数。为此,您必须知道/发现他们的确切签名。

    如果您有权访问strings 命令(在 cygwin 中可用),您可以针对 DLL 运行它。它将列出超过 4 个以 0 结尾的连续可打印字符的序列(请注意,在您不想安装 cygwin 的情况下,它真的很容易实现)。在这些“字符串”中,您将有垃圾函数签名,被 C++ 编译器破坏(参见:http://en.wikipedia.org/wiki/Name_mangling)。然后,您必须使用 undname.exe 解开您感兴趣的那些(假设 DLL 是由 Microsoft Visual 构建的;请参阅:http://msdn.microsoft.com/en-us/library/5x49w699.aspx

    ...您可能还想考虑 DependencyWalker。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多