显式加载 DLL

发布于 2024-08-01 13:51:21 字数 2690 浏览 6 评论 0原文

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

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

  1. 成员 typedef
    示例: typedef std::map服务器::KeyValueMap,typedef std::vector; Server::String Array
  2. 成员枚举
    示例:enum Server::Role {NONE,HIGH,LOW}
  3. 成员函数
    示例: void Server::connect(const StringArray,const KeyValueMap), void Server::disconnect()

实现来自谷歌搜索的代码,我设法加载可以调用断开连接函数的 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;}

我如何调用(例如)具有在 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,capacity,clear,get,isEMPTY,reserve,set,size

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

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

I'm trying to explicitly link with a DLL. No other resources is available except the DLL file itself and some documentation about the classes and its member functions.

From the documentation, each class comes with its own

  1. member typedef
    example: typedef std::map<std::string,std::string> Server::KeyValueMap, typedef std::vector<std::string> Server::String Array
  2. member enumeration
    example: enum Server::Role {NONE,HIGH,LOW}
  3. member function
    example: void Server::connect(const StringArray,const KeyValueMap), void Server::disconnect()

Implementing the codes from google search, i manage to load the dll can call the disconnect function..

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";

I got the function name above from depends.exe. Is this what is called decorated/mangled function names in 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;}

How do i call (for example) the connect member function which has the parameter datatype declared in the dll itself?

Edit

more info:

  • The DLL comes with an example implementation using Java. The Java example contains a Java wrapper generated using SWIG and a source code.
  • The documentation lists all the class, their member functions and also their datatypes. According to the doc, the list was generated from the C++ source codes.(??)
  • No other info was given (no info on what compiler was used to generate the DLL)

My colleague is implementing the interface using Java based on the Java example given, while I was asked to implement using C++. The DLL is from a third party company.

I'll ask them about the compiler. Any other info that i should get from them?

I had a quick read through about JNI but i dont understand how it's implemented in this case.

Update

i'm a little confused... (ok, ok... very confused)

  1. Do i call(GetProcAddress) each public member function separately only when i want to use them?
  2. Do i create a dummy class that imitates the class in the dll. Then inside the class definition, i call the equivalent function from the DLL? (Am i making sense here?) fnieto, is this what you're showing me at the end of your post?
  3. Is it possible to instantiate the whole class from the DLL?

I was trying to use the connect function described in my first post. From the Depends.exe DLL output,

  • std::map // KeyValueMap has the following member functions: del, empty, get, has_1key,set
  • std::vector // StringArray has the following member functions: add, capacity, clear, get, isEMPTY, reserve, set, size

which is different from the member functions of map and vector in my compiler (VS 2005)...

Any idea? or am i getting the wrong picture here...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

不念旧人 2024-08-08 13:51:21

如果我是你,我会非常小心:STL 库并不是为像这样跨编译边界而设计的。

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

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

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

(我什至没有触及名称修饰也可能因编译器而异的事实)

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

I would be very careful if I were you: the STL library was not designed to be used across compilation boundaries like that.

Not that it cannot be done, but you need to know what you are getting into.

This means that using STL classes across DLL boundaries can safely work only if you compile your EXE with the same exact compiler and version, and the same settings (especially DEBUG vs. RELEASE) as the original DLL. And I do mean "exact" match.

The C++ standard STL library is a specification of behavior, not implementation. Different compilers and even different revisions of the same compiler can, and will, differ on the code and data implementations. When your library returns you an std::map, it's giving you back the bits that work with the DLL's version of the STL, not necessarily the STL code compiled in your EXE.

(and I'm not even touching on the fact that name mangling can also differ from compiler to compiler)

Without more details on your circumstances, I can't be sure; but this can be a can of worms.

三岁铭 2024-08-08 13:51:21

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

Unless you use a disassembler and try to figure out the paramater types from assemly code, you can't. These kind of information is not stored in the DLL but in a header file coming with the DLL. If you don't have it, the DLL is propably not meant to be used by you.

丑疤怪 2024-08-08 13:51:21

为了与 DLL 链接,您需要:

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

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

链接器可以帮助您使用中间 DEF 从 DLL 生成 LIB。
有关更多详细信息,请参阅此问题:如何从 DLL 生成导入库?

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

In order to link with a DLL, you need:

  1. an import library (.LIB file), this describes the relation between C/C++ names and DLL exports.
  2. the C/C++ signatures of the exported items (usually functions), describing the calling convention, arguments and return value. This usually comes in a header file (.H).

From your question it looks like you can guess the signatures (#2), but you really need the LIB file (#1).

The linker can help you generate a LIB from a DLL using an intermediate DEF.
Refer to this question for more details: How to generate an import library from a DLL?

Then you need to pass the .lib as an "additional library" to the linker. The DLL must be available on the PATH or in the target folder.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文