0

我用LoadlibraryandGetprocaddress来链接一些WinApis来进行运行时链接。正如预期的那样,它工作正常。

但是对于某些 API,我只是用作-ldllname编译器选项。相同的选项会为某些 API 提供链接器错误,并且需要加载 dll。

这有什么特别的区别吗,即某些特定的 API 需要运行时链接,而其他 API 可以使用-ldllname选项?如何对这类 API 进行分类?

更新:我观察到的是支持 UNICODE 和 ANSI 的 API,即后缀为 "W" 和 "A" 的 API,通过静态链接本身得到解决?我对么?如果我错了,请纠正我!

为什么有些 API 需要运行时链接,而另一些则通过静态链接本身(-l 选项)解决?这有什么原因吗?

4

2 回答 2

1

基本上就是你描述的。我将在这里跳过非 Windows,但它本质上是相似的)。

所以,有两种不同的情况:

编译时(静态)链接:代码包括所有函数、类等的声明,但不包括正文。您必须在编译时提供正确的库文件(例如通过-ldllname):

void sayHello(void); // the declaration might be a bit more complicated, e.g. adding a calling convention or dllimport/dllexport, etc.

运行时(动态)链接:代码包括最少的函数体,主要是加载库和检索地址(通过您命名的函数):

HMODULE lib = LoadLibrary("hello.dll"); // loading happening somewhere once

void sayHello(void) {
    myfnproc call = GetProcAddress(lib, "sayHello");
    call(); // actual call
}

FreeLibrary(lib); // unloading happening somewhere else

虽然运行时方法更复杂,但它有一个很大的优势:您能够处理丢失的库。例如,如果用户缺少一些库,您可以告诉他在哪里下载它(甚至自己下载),并且可以轻松替换链接的代码(例如插件功能)。使用静态链接,您会很不走运:如果缺少依赖项,程序将无法运行。

于 2012-08-16T08:39:28.707 回答
1

我使用了负载库

这将是对 DLL 进行隐式依赖的示例。LoadLibrary 是一个由 kernel32.dll 导出的函数,它是一个 Windows api DLL。它实际上存在于两个版本中,LoadLibraryA 和 LoadLibraryW。分别是非 Unicode 和 Unicode 版本的函数。你会得到一个或另一个,这取决于你在编译时是否有 UNICODE 宏#defined。

-l因此,这与使用 GetProcAddress 动态链接导出完全相反,您必须通过该选项告诉链接器您的程序依赖于 kernel32 。在运行时,DLL 会在您自己的代码开始运行之前自动加载。

对操作系统 DLL 有隐式依赖是很正常的。而且不可避免的是,您永远不能动态链接 kernel32.dll,这将是鸡与蛋的问题。

于 2012-08-16T09:29:26.973 回答