C++ 显式加载 DLL
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1253769/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Explicit Loading of DLL
提问by justin
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.
我正在尝试与 DLL 显式链接。除了 DLL 文件本身和一些关于类及其成员函数的文档外,没有其他资源可用。
From the documentation, each class comes with its own
从文档中,每个类都有自己的
- member typedef
example:typedef std::map<std::string,std::string> Server::KeyValueMap, typedef std::vector<std::string> Server::String Array
- member enumeration
example:enum Server::Role {NONE,HIGH,LOW}
- member function
example:void Server::connect(const StringArray,const KeyValueMap), void Server::disconnect()
- 成员类型定义
示例:typedef std::map<std::string,std::string> Server::KeyValueMap, typedef std::vector<std::string> Server::String Array
- 成员枚举
示例:enum Server::Role {NONE,HIGH,LOW}
- 成员函数
示例: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..
实现来自谷歌搜索的代码,我设法加载 dll 可以调用断开功能..
dir.h
目录.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++?
我从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;}
How do i call (for example) the connectmember function which has the parameter datatype declared in the dll itself?
我如何调用(例如)具有在 dll 本身中声明的参数数据类型的连接成员函数?
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)
- DLL 带有一个使用 Java 的示例实现。Java 示例包含使用 SWIG 生成的 Java 包装器和源代码。
- 该文档列出了所有类、它们的成员函数以及它们的数据类型。根据文档,该列表是从 C++ 源代码生成的。(??)
- 没有提供其他信息(没有关于使用什么编译器生成 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.
我的同事正在根据给定的 Java 示例使用 Java 实现接口,而我被要求使用 C++ 实现。DLL 来自第三方公司。
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.
我快速阅读了 JNI,但我不明白在这种情况下它是如何实现的。
Update
更新
i'm a little confused... (ok, ok... very confused)
我有点困惑……(好吧,好吧……很困惑)
- Do i call(GetProcAddress) each public member function separately only when i want to use them?
- 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?
- Is it possible to instantiate the whole class from the DLL?
- 是否仅在我想使用它们时分别调用 (GetProcAddress) 每个公共成员函数?
- 我是否创建了一个模拟 dll 中的类的虚拟类。然后在类定义中,我从 DLL 调用等效函数?(我在这里说得通吗?) fnieto,这就是你在帖子末尾向我展示的内容吗?
- 是否可以从 DLL 实例化整个类?
I was trying to use the connect function described in my first post. From the Depends.exe DLL output,
我试图使用我的第一篇文章中描述的连接功能。从 Depends.exe DLL 输出,
- 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
- std::map // KeyValueMap 有如下成员函数:del、empty、get、has_1key、set
- std::vector // StringArray 有以下成员函数:add、capability、clear、get、isEMPTY、reserve、set、size
which is different from the member functions of map and vector in my compiler (VS 2005)...
这与我的编译器(VS 2005)中的 map 和 vector 的成员函数不同...
Any idea? or am i getting the wrong picture here...
任何的想法?或者我在这里得到了错误的图片......
回答by Frank Bollack
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.
除非您使用反汇编器并尝试从汇编代码中找出参数类型,否则您不能。这些信息并不存储在 DLL 中,而是存储在 DLL 附带的头文件中。如果您没有它,那么您可能不打算使用该 DLL。
回答by Euro Micelli
I would be very careful if I were you: the STL library was not designed to be used across compilation boundaries like that.
如果我是你,我会非常小心:STL 库不是为了像那样跨编译边界使用而设计的。
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.
这意味着,仅当您使用与原始 DLL 相同的确切编译器和版本以及相同的设置(尤其是调试与发布)来编译 EXE 时,才能安全地使用跨 DLL 边界的 STL 类。我的意思是“完全”匹配。
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.
C++ 标准 STL 库是行为规范,而不是实现。不同的编译器,甚至同一个编译器的不同版本,在代码和数据实现上可能并且将会不同。当您的库返回一个 . 时std::map
,它会返回与 DLL 版本的 STL 一起使用的位,不一定是在您的 EXE 中编译的 STL 代码。
(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.
如果没有关于您的情况的更多详细信息,我无法确定;但这可能是一罐蠕虫。
回答by rustyx
In order to link with a DLL, you need:
为了与 DLL 链接,您需要:
- an import library (.LIB file), this describes the relation between C/C++ names and DLL exports.
- 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).
- 一个导入库(.LIB 文件),它描述了 C/C++ 名称和 DLL 导出之间的关系。
- 导出项(通常是函数)的 C/C++ 签名,描述调用约定、参数和返回值。这通常出现在头文件 (.H) 中。
From your question it looks like you can guess the signatures (#2), but you really need the LIB file (#1).
从您的问题来看,您似乎可以猜出签名(#2),但您确实需要 LIB 文件(#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?
链接器可以帮助您使用中间 DEF 从 DLL 生成 LIB。有关更多详细信息,请参阅此问题:如何从 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.
然后您需要将 .lib 作为“附加库”传递给链接器。DLL 必须在 PATH 或目标文件夹中可用。