C++ - LoadLibrary() 实际上链接到库吗?
Posted
技术标签:
【中文标题】C++ - LoadLibrary() 实际上链接到库吗?【英文标题】:C++ - Does LoadLibrary() actually link to the library? 【发布时间】:2013-06-18 19:06:27 【问题描述】:我正在使用 Code::Blocks 并且讨厌手动链接 DLL。我找到了LoadLibrary()
函数,我想知道它是否像.a
或.lib
文件那样工作。这个功能是这样工作的吗?如果没有,我可以在编程方面(如果有的话)做些什么来链接 DLL 而不必通过 Project < Build options < Linker settings < add < ...
方法链接 DLL?
【问题讨论】:
在链接时不链接到 DLL,也不在运行时加载静态库。 @chris:实际上,您在编译时确实链接到动态库(即使只是到存根,或任何其他特定的加载程序魔法)。否则您的程序将如何访问它包含的符号? ;) @syam,好吧,至少你真的不需要做任何特别的事情来担心它。 @chris: "你真的不需要做任何特别的事情" => 显然,在编译器的命令行上指定-lfoobar
以链接到libfoobar.so
(或任何 Windows 等价物,你明白了)对于 OP 来说似乎是“特别的东西”(并且是一种负担)。但我敢肯定,当他看到 LoadLibrary/GetProcAddress
(resp. dlopen/dlsym
) 真正意味着多少工作时,他很快就会改变主意。 ;)
【参考方案1】:
LoadLibrary
将请求的库(以及它需要的所有库)加载到进程的地址空间中。为了访问该库中的任何代码/数据,您需要找出新加载的内存区域中的代码或数据地址。您需要使用GetProcAddress
。
此过程与在构建时添加库之间的区别在于,对于构建时库,编译器准备一个引用给定函数的位置列表,链接器将该列表放入 .exe,然后运行时链接器加载该库对函数名执行相当于GetProcAddress
的操作,并将地址放入编译器标记的所有位置。
当你没有这个自动支持时,你必须声明一个指向函数的指针,自己调用GetProcAddress
,并将返回的值赋给你的函数指针。然后,您可以像调用任何其他 C 函数一样调用该函数(注意“C”部分 - 当您使用 C++ 时,上述过程会因名称修改而变得复杂,因此请使用 extern "C"
)
【讨论】:
【参考方案2】:LoadLibrary()
在运行时加载一个 DLL。通常在编译 EXE 时链接,此时链接 DLL 就像静态库一样。如果需要在运行时动态加载库,请使用LoadLibrary()
。
例如,当您实现插件系统时,这是否有用,因为您事先不知道库。
【讨论】:
没有。通过 eproject 设置,oyu 可以准确地知道要附加到程序中的 DLL。程序启动时会自动加载 DLL。使用 LoadLibrary 意味着您必须在代码中手动执行此操作,并且也不知道哪些符号可用。【参考方案3】:根本不是它的工作原理。 LoadLibrary
用于加载“在编译时未知”的 DLL - 例如程序扩展/插件或“此 DLL 用于 SSE,该 DLL 用于非 SSE”基于“硬件可以做什么——也可以考虑拥有每个连接类型的 DLL 到电子邮件服务器或类似的东西,这样电子邮件程序就不必“携带”所有不同的变体,当只有一个用于任何特定的电子邮件地址时。
另外,要使用这样加载的DLL,需要使用GetProcAddress
来获取DLL中函数的地址。这与在构建时将 DLL 链接到项目中非常不同,其中函数只是通过系统加载器函数“自动”出现,这些函数加载在构建时添加到项目中的 DLL。
【讨论】:
【参考方案4】:与静态或动态库链接相反,LoadLibrary
不会使库的符号直接可用于您的程序。您需要在运行时调用GetProcAddress
以获取指向您要调用的函数的指针。
正如@Devolus 所提到的,这是实现插件系统和/或访问可选组件的好方法。但是,由于您的程序无法以透明的方式使用这些符号,因此这对于普通用途来说并不实用。
【讨论】:
以上是关于C++ - LoadLibrary() 实际上链接到库吗?的主要内容,如果未能解决你的问题,请参考以下文章
在 C++ 上使用带有 LoadLibrary() 方法的库 dll
使用 loadLibrary() 在 java 中调用 c++ dll
调试通过 LoadLibrary() 加载到 Excel 中的 C++ DLL
Android 11 - 本机 C++ 库的 System.loadLibrary 需要 60 多秒,在 Android 10 及更低版本上运行速度非常快