【问题标题】:Converting a Windows Dll to .lib for C++ Visual Studio 2008将 Windows Dll 转换为 C++ Visual Studio 2008 的 .lib
【发布时间】:2010-12-04 22:14:09
【问题描述】:

我知道有一个名为 Dll 的工具,但开发人员要价 1000 美元。 我只需要转换一个库,一次,所以很难证明这个价格是合理的。

我尝试了 IMPLIB32.EXE,但我得到的是空的 .lib 文件。 我怎样才能做到这一点? 也许我可以编写一个简单的转换应用程序?

添加1:

Dll 通常是 stdcall 而不是 cdecl,并且是用较旧的 C 语言编写的,例如语言不是 C#、.NET 或 C++。我现在需要从 C++ 应用程序中调用它们。 SQLite.dll 或 zlib.dll 就是一个例子。 我无权访问这些 dll 的 .lib 文件。

添加2:

我为 VS2008 重写了这段代码 http://floodyberry.wordpress.com/2008/09/08/generating-dll-wrappers/ 并包括可在此处下载的示例 Dll 等: http://www.transferbigfiles.com/Get.aspx?id=7d86fa0b-6ddc-4f6f-8d31-2c20824aae9a 这反过来会产生一个创建 Dll 的项目。当我尝试编译 Dll 时,出现链接器错误: AddShow.dll:致命错误 LNK1107:无效或损坏的文件:无法在 0x300 读取 此处描述: http://list.isis.vanderbilt.edu/pipermail/udm-users/2006-March/000664.html 不知道如何进行。这么近,这么远

接下来我们转到这个方法

http://www.coderetard.com/2009/01/21/generate-a-lib-from-a-dll-with-visual-studio/

使用参数 /exports C:\path\to\AddShow.dll 运行 dumpbin 绝对什么都不做 经过一番研究

http://msdn.microsoft.com/en-us/library/aa446532.aspx 似乎需要来自 common/ide 文件夹的 mspdb71.dll(现在是 mspdb80.dll) dumpbin.exe 现在运行时出现错误:

致命错误 LNK1106:无效文件或磁盘已满:无法查找 0x6179A 这些线程表明dumpbin.exe的版本可能是问题

我有 Microsoft (R) COFF/PE Dumper 版本 9.00.30729.01

所以我尝试了 Microsoft (R) COFF 二进制文件转储程序版本 5.12.8078 没有成功。 经过大量阅读,我不再靠近

http://support.microsoft.com/kb/815645 http://support.microsoft.com/kb/839286 http://markmail.org/message/p5vwzyfyv3bs6z34 http://fixunix.com/programmer/94825-fatal-error-lnk1106-invalid-file-disk-full.html

当我运行 ProcMon 时,我看到第一次出现 queryopen 和 sqlite3.dll 时 svchost.exe 尝试打开它并失败并出现错误 PATH NOT FOUND。路径是 C:\Program Files\Microsoft Visual Studio 9.0\VC\bin\SQLITE3.DLL 并且是正确的。如果我把它放在 C 驱动器的根目录,那么我会收到 NAME NOT FOUND 错误:

C:\Program Files\Microsoft Visual Studio 9.0\VC\bin\link.exe.Local

C:\Program Files\Microsoft Visual Studio 9.0\VC\bin\dumpbin.exe.Local

分别来自link.exe 和dumpbin.exe。我使用的是 XPSP3 而不是 Vista,这是我对 sysinternals 知识的限制。这些 .local 文件是什么?

(csrss.exe 也找不到一些清单文件。)

所以还没有成功,只是更神秘

添加 3:

我尝试从安装位置\Program Files\Microsoft Visual Studio 8\VC\bin 运行dumpbin.exe,但操作系统说找不到mspdb80.dll。我从 \Program Files\Microsoft Visual Studio 8\Common7\IDE 复制了 mspdb80.dll 以尝试运行 dumpbin.exe。

现在我得到错误: “c1902程序数据库管理器不匹配请检查你的安装”

如果我从 \Program Files\Microsoft Visual Studio 8\VC\bin 中删除 mspdb80.dll,错误就会消失!但我无法运行 dumpbin.exe。

添加了 4 个:

我终于能够通过将以下文件复制到文件夹来运行 dumpbin:

dumpbin.exe 链接程序 库文件 mspdb80.dll

我确实得到了错误:

致命错误 LNK1248:图像大小 (FFFFFXXX) 超出最大允许大小 (80000000)

一次,但替换 dll 解决了这个问题。大概它被损坏了?

然后我进入说明中的下一步: http://www.coderetard.com/2009/01/21/generate-a-lib-from-a-dll-with-visual-studio/ http://support.microsoft.com/kb/131313 并得到错误: 目标平台不支持警告 lnk4017 语句被忽略 原来这是因为我指定了 .dll 而不是 .def 文件。

然后将生成的 .Lib 和 .exp 文件添加到 VS2008 项目中并编译和运行。然后调试器报错: 运行时检查失败 #0 - ESP 的值未在函数调用中正确保存...

正如这里提到的 "Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call" after successful C# callback from the C++ code of GameSpy lib 这是因为我在我的 dll 中使用了 stdcall 并在我的应用程序中声明了 __cdecl。

extern "C" { // put Dll C function prototypes here
 int __cdecl AddTwoNum(int n, double f); // __stdcall
}

因此,将其更改为 __stdcall 应该可以解决您认为的问题.. 但可惜没有。

现在我收到一个链接错误: 错误 LNK2001:未解析的外部符号 _AddTwoNum@12

出于某种原因,这是一个修饰函数名。为什么?

添加了n:

这原来是因为 .lib 文件是使用带有 STDCALL 函数的 dll 制作的。 STDCALL 要求调用者清理堆栈,以便将参数的字节数附加到带有 @ 符号的函数名称中。在这种情况下,我有三个 4Byte 整数,总共 12 个字节。

一旦我从使用 CDECL 调用约定创建的 dll 重新制作了 .lib 文件,那么一切都很好。

【问题讨论】:

  • 这是本地 C/C++ DLL 还是 .NET DLL?
  • 等一下......至少在zlib和sqlite3的情况下,获取原始导入库不是更容易吗?
  • sqlite 只是大家都听说过的一个例子。我知道为此存在原始的 inport 库,但我试图转换的 dll (AddTwoNum.dll) 没有。
  • 我认为你应该发布一个关于你的更新的新问题。它可能会受益于一个新的标题和一组新的回答者。

标签: c++ windows visual-c++ dllimport


【解决方案1】:

开源edll 有自己的内部 COFF 加载器。 edll 是为完全不同的目的而编写的,但由于它内部有独立的 COFF 加载器,也许可以将您的 .dll 合并到 .exe 中的二进制流或资源中,然后在运行时使用 edll 的 COFF 加载器来加载内置的 dll .

【讨论】:

    【解决方案2】:

    我已经成功地使用http://wyw.dcweb.cn/dllfaq.htm 中的详细信息从 DLL 中获取了一个库。您的里程可能会有所不同。我已经使用它从 python DLL 中获取了一个库来构建一些用“C”编写的 python 扩展。

    【讨论】:

      【解决方案3】:

      您也可以采用动态方式,使用LoadLibrary()GetProcAddress()

      (参见第二个链接的示例)。

      【讨论】:

      • 谢谢。是的,那总是一个好方法。这会起作用,但这个问题的目的是在 VS2008 项目中包含该库,而无需花费 1000 美元
      【解决方案4】:

      【讨论】:

      • 谢谢。我花了几个小时使用 dumpbin.exe 并没有运气。我的笔记在上面
      【解决方案5】:

      我似乎无法评论他的回答(我需要更多的声誉?),但您可以尝试使用我的.dll wrapper generator 来创建我建议的存根 .dll。

      【讨论】:

      • 感谢您提供此代码。我在终点线被难住了。见上文
      • 我发现:social.msdn.microsoft.com/Forums/en/vcgeneral/thread/… 你链接的是 .dll 而不是 .lib?
      • 啊啊。那是我错过的关键部分。现在它起作用了!非常感谢代码。
      • 我理解了这个概念,新的 dll 项目实际上是原始 dll 的包装器,它只是使用 LoadLibrary() 和 GetProcAddress() 动态加载它,对吗?
      • 是的。它的设计使您可以在无法访问源代码时轻松生成包装器 .dll 来拦截/修改调用。例如一个 ws2_32.dll 包装器,用于修改网络调用,例如您想要手动限制应用程序等。
      【解决方案6】:

      在 zlib 或 sqlite 等情况下,您可以直接下载源代码并编译自己的 lib 文件。事实上,前几天我刚刚为 zlib 做了这个,我从www.zlib.net (direct zlib 1.2.3 download) 下载了源代码,打开了提供的 Visual Studio 项目文件并编译了该 lib 的调试和发布版本。 sqlite我没试过,但是看到他们有源码,应该不难做到。

      如果是专有 dll,您可以尝试向原始开发人员或公司索取 lib 文件,或者编写您自己的 iain 建议的存根 dll,或者采用 RaphaelSP 的动态路径。

      如果它们以 C 语言导出(没有 C++ 名称修改),我会自己走动态路线。

      【讨论】:

      • 是的。我希望转换的 Dll 没有 .def 或 .lib 文件,只有标头可用。
      【解决方案7】:

      如果您联系 Dll to lib 工具的开发人员,他们可能愿意给您折扣。

      我以前遇到过这种情况(我只需要一次昂贵的工具),有时我成功地获得了很大的折扣。

      尝试永远不会有坏处。

      祝你好运。

      【讨论】:

      • 你是对的。我做到了。他接受了 100 美元的产品,但在做了这么多工作之后,我要自己动手了。
      【解决方案8】:

      我假设您想在 C/C++ 中调用 dll 中的某些函数/方法,而无需访问 lib 文件以与之链接。

      如果你知道你需要的函数的签名,你可以:

      • 创建您自己的 dll 存根版本
      • 创建一个 dll 项目,与您要使用的 dll 同名
      • 添加要调用的函数的存根实现
      • 签名非常重要,使用depends.exe 或dumpbin.exe 来检查它们是否匹配。
      • 然后编写/构建您的程序以链接到存根 dll
      • 运行程序用真实的替换存根dll

      【讨论】:

      • 您认为是正确的。我通常有 .h 头文件,所以我知道签名。您详细介绍的步骤对我来说都是新的。如果您能详细说明它们或链接到演示,我将非常感激。
      • 基本上,这归结为创建一个新的 DLL 项目,该项目将生成与您缺少的相同的导入库。
      • 对。这只是在艰难的水域中航行到达那里的一个案例
      【解决方案9】:

      This 应该是一个免费的转换工具。我不确定它是否像“有限试用版”那样“免费”,信息不是很清楚。如果您已经对此进行了测试,请编辑您的问题,我将删除此答案。

      【讨论】:

      • 你是对的。我给了他100美元,他同意了。我更喜欢有自己的解决方案。
      • @Mike Trader - 你不是说我要求折扣是对的吗? :)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-02
      • 2018-09-12
      • 1970-01-01
      • 1970-01-01
      • 2011-01-02
      相关资源
      最近更新 更多