显式加载DLL

时间:2009-08-10 08:44:57

标签: c++ class dll explicit

我正在尝试显式链接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()
  4. 从谷歌搜索实现代码,我设法加载DLL可以调用断开连接函数..

    dir.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;}
    

    如何调用(例如) connect 成员函数,该函数具有在dll中声明的参数datatype?

    修改

    更多信息:

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

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

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

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

    更新

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

    1. 只有当我想使用它们时,我才会单独调用(GetProcAddress)每个公共成员函数吗?
    2. 我是否创建了一个模仿dll类的虚拟类。然后在类定义中,我从DLL中调用等效函数? (我在这里有意义吗?)fnieto,这是你在帖子结束时向我展示的内容吗?
    3. 是否可以从DLL中实例化整个类?
    4. 我试图使用我的第一篇文章中描述的连接功能。从Depends.exe DLL输出

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

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

      有什么想法吗?或者我在这里得到了错误的图片......

3 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:0)

如果我是你,我会非常小心:STL库不是设计用于那样的编译边界。

不是说它无法完成,而是你需要知道你要进入的目的。

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

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

(我甚至没有涉及名称修改也可能因编译器而异的事实)

如果没有关于你情况的更多细节,我无法确定;但这可能是一堆蠕虫。

答案 2 :(得分:0)

要与DLL链接,您需要:

  1. 一个导入库(.LIB文件),它描述了C / C ++名称和DLL导出之间的关系。
  2. 导出项(通常是函数)的C / C ++签名,描述调用约定,参数和返回值。这通常出现在头文件(.H)中。
  3. 从您的问题看起来您可以猜出签名(#2),但您确实需要LIB文件(#1)。

    链接器可以帮助您使用中间DEF从DLL生成LIB。 有关详细信息,请参阅此问题:How to generate an import library from a DLL?

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