模块和共享库有什么区别?

45

标题已经涵盖了主要内容,模块和共享库有什么区别?我在CMake的add_library命令中发现了这个区别,他们说:

  

共享库是动态链接并在运行时加载的。模块库是插件,不会链接到其他目标中,但可以使用类似于dlopen的功能在运行时动态加载。

但我可以使用dlopen()来加载共享对象,对吗?

3个回答

44

这两者之间的区别在于,你可以使用链接器将库链接到一个共享库中,但你无法将模块链接到链接器中。在某些平台上例外。

所以为了能够完全跨平台且在CMake工作的任何地方都能运行,你不应该这样做:

# This is a big NO-NO:
add_library(mylib MODULE ${srcs})
target_link_libraries(myexe mylib)

公平地说,在Windows上,它们都只是dll文件,因此这段代码实际上可能会起作用。但是当你将其带到一个无法链接到MODULE的平台时,你会遇到一个错误。

底线:如果需要链接到库,请使用SHARED。如果可以确保库仅被动态加载,则可以安全地使用MODULE。(甚至可能更好,以便检测是否有人试图链接到它...)


有人知道这可能是在哪些平台上出现的问题吗? - mhsmith
但是您不能使用链接器链接到一个模块。在某些平台上,即使它们可以作为库添加,如果没有使用任何符号,您是否实际上正在Windows上链接到它? - pooya13
重点是,如果一个库是模块,那么你不应该试图去链接它。你应该使用 LoadLibrary 或 dlopen 加载它,并动态地调用它。当我说后面的话“所以这段代码实际上可能会工作”时,我的意思是 CMake 代码调用 target_link_libraries。但对于模块库来说这是不可取的,即使它似乎已经“工作了”(更正确地说是“没有产生错误”),也不要这样做。 - DLRdave
似乎我们总是可以使用共享库而不是模块库。那么为什么还有叫做模块库的东西呢? - zsf222
Linux 上的两个目标是否相同? - fluter

12

我认为要区分的是,在编译时开发人员指定共享库,必须存在才能运行应用程序,尽管它们的方法在运行时加载。模块(即插件)在运行时添加附加支持,但不是必需的。是的,您可以使用dlopen()打开共享库,但在这种情况下,它不是程序的必需部分,并且作为模块而非共享库中的函数。


7
另一个区别在于如何处理 ..._OUTPUT_DIRECTORY..._OUTPUT_NAME
模块库始终被视为库目标。对于非 DLL 平台,共享库被视为库目标。对于 DLL 平台,共享库的 DLL 部分被视为运行时目标,并且相应的导入库被视为存档目标。所有基于 Windows 的系统,包括 Cygwin 在内,都是 DLL 平台。
例如,这意味着如果您在 Windows 上编译一个 SHARED 库,LIBRARY_OUTPUT_DIRECTORY 将被忽略,因为它会查看 ARCHIVE_OUTPUT_DIRECTORYRUNTIME_OUTPUT_DIRECTORY

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接