【问题标题】:Calling two functions with the same name from two different C DLLs从两个不同的 C DLL 调用具有相同名称的两个函数
【发布时间】:2010-09-22 02:13:56
【问题描述】:

我需要在同一个可执行文件中访问两个 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 之前不会出现问题,这甚至可能在测试通过时被遗漏。

【问题讨论】:

    标签: c windows visual-studio-2008 dll


    【解决方案1】:

    过去,您可以使用链接器 .def 文件“重命名”导入的符号。您可能仍然可以,但是自从 .def 文件被广泛使用以来已经很长时间了,很难找到文档。

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

    这里是描述 IMPORTS 指令的页面:

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

    其他笨拙的替代品是:

    1. 为冲突的 API 创建包装函数。这些功能可以跳LoadLibrary()/GetProcAddress() 跳舞。所有其他不冲突的函数都可以像往常一样隐式链接。实际上,这个解决方案可能是这个答案中 3 个中最不笨拙的一个。

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        在我对此事进行了更多思考之后,我设法得出了迈克 B 的笨拙替代方案 #2(或 #3,如果你算上最初的建议)。

        这是我最喜欢的三个对于我的具体案例,因为它似乎需要最少的工作量,并且对于新看代码的人来说可能是最容易破译的。我相信我可以按照以下步骤启动并运行:

        1. 使用一些正则表达式魔法并查找/替换将带有函数调用的头文件转换为包装头文件和包装器实现文件。 (包装器 dll 中的每个方法都通过名称中的一些常见新元素来区分,节省了我解决冲突的时间)因此,FunctionCall() 在每个包装器 dll 中变为 WrapperOneFunctionCall() 和 WrapperTwoFunctionCall()。
        2. 将包装器 dll 链接到其对应的基础 dll。
        3. 将我的可执行文件链接到包装器 dll,删除到基本 dll 的链接,但仍然包括不需要从基本 dll 解析的常量、枚举和结构定义(因为我的包装器函数仍然采用相同的参数类型)

        如果有人还在阅读这个帖子,我的后续问题是:“这个解决方案有什么问题吗?”

        感谢响应者的帮助。

        【讨论】:

        • 由于这是 C++,您还可以考虑使用命名空间来区分这两个函数,而不是以必须进一步解释的特殊目的方式修改函数名称。缺点是这对 C 语言调用者不起作用。
        • 我发现您使用 LoadLibrary 和 GetProcAddress 的原始提案最合乎逻辑,实际上最容易实现。您能否详细说明为什么您对这种方法有疑问并寻找替代方法?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-11-12
        • 2011-04-10
        • 1970-01-01
        • 2011-06-01
        • 1970-01-01
        • 2019-10-14
        相关资源
        最近更新 更多