【问题标题】:Explicit Loading of DLL显式加载 DLL
【发布时间】:2009-08-10 08:44:57
【问题描述】:

我正在尝试显式链接 DLL。除了 DLL 文件本身和一些关于类及其成员函数的文档之外,没有其他可用资源。

从文档来看,每个类都有自己的

  1. 成员类型定义
    例如:typedef std::map<std::string,std::string> Server::KeyValueMap, typedef std::vector<std::string> Server::String Array
  2. 成员枚举
    例如:enum Server::Role {NONE,HIGH,LOW}
  3. 成员函数
    例如:void Server::connect(const StringArray,const KeyValueMap), void Server::disconnect()

实现google搜索的代码,我设法加载dll可以调用断开功能..

目录.h

LPCSTR disconnect = "_Java_mas_com_oa_rollings_as_apiJNI_Server_1disconnect@20";  
LPCSTR connect =   
"_Java_mas_com_oa_rollings_as_apiJNI_Server_1connect@20";

我从depends.exe 得到了上面的函数名。这就是 C++ 中所谓的修饰/损坏函数名称吗?

main.cpp

#include <iostream>
#include <windows.h>
#include <tchar.h>
#include "dir.h"

typedef void (*pdisconnect)();

int main()
{
    HMODULE DLL = LoadLibrary(_T("server.dll"));  
    pdisconnect _pdisconnect;`

    if(DLL)
    {
        std::cout<< "DLL loaded!" << std::endl;
        _disconnect = (pdisconnect)GetProcAddress(DLL,disconnect);


        if(_disconnect)
        {
            std::cout   << "Successful link to function in DLL!" << std::endl;
        }

        else
        {
            std::cout<< "Unable to link to function in DLL!" << std::endl;
        }
    }  
    else    
{  
std::cout<< "DLL failed to load!" << std::endl;  
}  
FreeLibrary (DLL);  
return 0;}

我如何调用(例如)具有在 dll 本身中声明的参数数据类型的 connect 成员函数?

编辑

更多信息:

  • DLL 附带一个使用 Java 的示例实现。 Java 示例包含使用 SWIG 生成的 Java 包装器和源代码。
  • 文档列出了所有类、它们的成员函数以及它们的数据类型。根据文档,该列表是从 C++ 源代码生成的。(??)
  • 没有提供其他信息(没有关于使用什么编译器生成 DLL 的信息)

我的同事正在根据给出的 Java 示例使用 Java 实现接口,而我被要求使用 C++ 实现。 DLL 来自第三方公司。

我会问他们关于编译器的问题。我应该从他们那里得到任何其他信息吗?

我快速阅读了有关 JNI 的内容,但我不明白在这种情况下它是如何实现的。

更新

我有点困惑……(好吧,好吧……很困惑)

  1. 是否只有在我想使用每个公共成员函数时才单独调用(GetProcAddress)?
  2. 我是否创建了一个模拟 dll 中的类的虚拟类。然后在类定义中,我从 DLL 调用等效函数? (我在这里有意义吗?) fnieto,这是您在帖子末尾向我展示的内容吗?
  3. 是否可以从 DLL 实例化整个类?

我试图使用我第一篇文章中描述的连接功能。从 Depends.exe DLL 输出中,

  • std::map // KeyValueMap 有以下成员函数:del、empty、get、has_1key、set
  • std::vector // StringArray 有以下成员函数:add、capability、clear、get、isEMPTY、reserve、set、size

这与我的编译器(VS 2005)中map和vector的成员函数不同...

有什么想法吗?还是我在这里得到错误的图片...

【问题讨论】:

    标签: c++ class dll explicit


    【解决方案1】:

    除非您使用反汇编程序并尝试从汇编代码中找出参数类型,否则您做不到。这些信息不存储在 DLL 中,而是存储在 DLL 附带的头文件中。如果您没有它,则该 DLL 可能不适合您使用。

    【讨论】:

      【解决方案2】:

      如果我是你,我会非常小心:STL 库并非设计用于跨编译边界使用。

      不是说做不到,而是你需要知道你在做什么。

      这意味着,只有使用与原始 DLL 完全相同的编译器和版本以及相同的设置(尤其是 DEBUG 与 RELEASE)来编译 EXE,跨 DLL 边界使用 STL 类才能安全地工作。我的意思是“精确”匹配。

      C++ 标准 STL 库是行为规范,而不是实现。不同的编译器,甚至同一编译器的不同版本,在代码和数据实现上可以并且将会有所不同。当您的库返回 std::map 时,它会将与 DLL 版本的 STL 一起使用的位返回给您,而不一定是在您的 EXE 中编译的 STL 代码。

      (我什至没有提到名称修改也可能因编译器而异)

      如果没有关于您的情况的更多详细信息,我无法确定;但这可能是一罐蠕虫。

      【讨论】:

      • 感谢您的回复...您还需要什么其他详细信息?...我不确定我应该寻找哪些详细信息...
      • 嗯——本质上——DLL 是从哪里来的。如果你说它是一个传给你的 DLL,而你不知道它来自哪里,或者使用了什么编译器,我会非常担心。如果它是由您组织中的其他人开发的,并且您确切知道他们使用的是什么编译器,并且您可以与其他人协调您的编译器升级,我就不会那么担心了。就像@fnieto 一样,我没有注意到 Java Native Interface 连接;我没有使用 JNI 的经验。
      【解决方案3】:

      要与 DLL 链接,您需要:

      1. 一个导入库(.LIB 文件),它描述了 C/C++ 名称和 DLL 导出之间的关系。
      2. 导出项(通常是函数)的 C/C++ 签名,描述调用约定、参数和返回值。这通常出现在头文件 (.H) 中。

      从您的问题看来,您可以猜出签名(#2),但您确实需要 LIB 文件(#1)。

      链接器可以帮助您使用中间 DEF 从 DLL 生成 LIB。 更多细节请参考这个问题:How to generate an import library from a DLL?

      然后您需要将 .lib 作为“附加库”传递给链接器。 DLL 必须在 PATH 或目标文件夹中可用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-12-05
        • 1970-01-01
        • 1970-01-01
        • 2017-06-26
        • 2012-01-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多