从两个不同的C DLL调用两个具有相同名称的函数

时间:2008-11-12 23:04:27

标签: c windows visual-studio-2008 dll

我需要在同一个可执行文件中访问两个C DLL。我有两个库的头文件和.LIB文件。不幸的是,我需要访问的函数的子集具有完全相同的名称。到目前为止,我能够提出的最佳解决方案是使用LoadLibrary加载其中一个DLL并使用GetProcAddress显式调用其方法。有没有办法让我隐式加载两个库,并以某种方式给编译器一个提示,在一种情况下,我想在DLL A中调用OpenApi,在另一种情况下,我想在DLL B中调用OpenApi?

我正在使用Visual Studio 2008和相应的C运行时库(msvcr90.dll)在C ++中开发可执行文件。

[编辑]

评论者Ilya在下面询问我对GetProcAddress解决方案不喜欢的内容。我不喜欢它有两个原因:

  1. 它使代码更复杂。调用函数的一行代码被三行代码替换,一行用于定义函数签名,一行用于调用GetProcAddress,另一行用于实际调用函数。
  2. 它更容易出现运行时错误。如果我拼错了函数名称或弄乱了签名,我在运行时才会看到错误。假设我决定集成新版本的DLL并且其中一个方法名称已更改,它将编译得很好,并且在实际调用GetProcAddress之前不会出现问题,甚至可能在测试过程中错过。

3 个答案:

答案 0 :(得分:4)

过去,您可以使用链接器.def文件“重命名”导入的符号。你可能还可以,但是.def文件被广泛使用已经很久了,很难找到文档。

当前的MSDN文档将IMPORTS指令列为“保留关键字”。我不确定这是否意味着他们删除了这些功能,或者他们是否只是不想再支持它了。

这是描述IMPORTS指令的页面:

http://www.digitalmars.com/ctg/ctgDefFiles.html#imports

其他kludgy替代方案是:

  1. 为冲突的API创建包装函数。这些功能可以进行LoadLibrary()/GetProcAddress()舞蹈。所有其他非冲突函数可以正常隐式链接。实际上,这个解决方案可能是这个答案中3中最少的一个。

  2. 创建2个包装器DLL,使每个DLL仅链接到具有冲突名称的一个或另一个库。在包装器DLL中使用不同的名称,这些名称只是简单地转移到真正的库中。请注意,包装器库不需要包装所有API - 它们只需要包装冲突的API。

答案 1 :(得分:1)

您可以构建新的导入库文件,重命名有问题的函数,然后使用这些新的导入库隐式链接两个DLL模块。以下是介绍该过程的Microsoft知识库文章:How To Create 32-bit Import Libraries Without .OBJs or Source

答案 2 :(得分:1)

在我对此事进行了一些考虑之后,我设法得到了Mike B的kludgy替代品#2(或者如果算上原来的建议,那么#3)。

对于我的特定情况,这是我最喜欢的三个,因为它似乎需要的工作量最少,并且可能是最明显的解密新代码的人。我相信我可以按照这些步骤启动并运行:

  1. 使用一些正则表达式魔术和find / replace来将头文件与我所拥有的函数调用一起转换为包装器头文件和包装器实现文件。 (其中包装器dll中的每个方法都通过名称的一些常见新元素来区分,从而节省了必须解决冲突的时间)因此,FunctionCall()在每个相应的包装器dll中变为WrapperOneFunctionCall()和WrapperTwoFunctionCall()。
  2. 将包装器dll链接到其对应的基本dll。
  3. 将我的可执行文件链接到包装器dll,删除指向基本dll的链接,但仍然包含不需要从基本dll解析的常量,枚举和结构定义(因为我的包装器函数仍然使用相同的参数类型)
  4. 如果有人还在阅读这个帖子,我的后续问题就是:“这个解决方案有什么问题吗?”

    感谢响应者的帮助。