运行时链接API和“-ldllname”编译器选项

时间:2012-08-16 08:31:58

标签: c winapi dll linker

我使用LoadlibraryGetprocaddress来链接一些WinApis以进行运行时链接。它按预期正常工作。

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

这有什么特别的区别,那就是某些特定的API需要运行时链接,其他API将与-ldllname选项一起使用?如何区分这类API?

  

更新:我观察到的是支持UNICODE和ANSI的API,即:   以“W”和“A”为后缀的API将通过静态解析   连接自己?我对么?如果我错了,请纠正我!

     

为什么某些API需要运行时链接,而其他API则需要使用Static解析   链接自己(-l选项)?有什么理由吗?

2 个答案:

答案 0 :(得分: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

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

答案 1 :(得分:1)

  

我使用了Loadlibrary

这将是对DLL进行隐式依赖的示例。 LoadLibrary是由kernel ap.dll(Windows api DLL)导出的函数。它实际上存在两个版本,LoadLibraryA和LoadLibraryW。分别是非Unicode和Unicode版本的函数。您将获得其中一个,具体取决于编译时是否具有UNICODE宏#defined。

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

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