标题大部分都涵盖了,模块和共享库有什么区别?我刚刚在 CMake 的
add_library
命令中发现了这种区别,他们说:
共享库动态链接并在运行时加载。 MODULE 库是未链接到其他目标的插件,但可以使用类似 dlopen 的功能在运行时动态加载。
但是我可以使用 dlopen() 加载共享对象,不是吗?
不同之处在于,您可以使用链接器链接到共享库,但不能使用链接器链接到模块。在一些平台上。
所以...为了完全跨平台并在 CMake 工作的任何地方工作,你永远不应该这样做:
# This is a big NO-NO:
add_library(mylib MODULE ${srcs})
target_link_libraries(myexe mylib)
公平地说,在 Windows 上,它们都只是 dll,因此这段代码实际上可能有效。但是当你把它带到一个无法链接到模块的平台时,你会遇到错误。
底线:如果需要链接到库,请使用 SHARED。如果您保证该库将“仅”被动态加载,那么使用模块是安全的。 (也许更好的是帮助检测是否有人确实尝试链接到它......)
(函数和变量),这些符号在库中未定义(并且未在与其链接的库中定义)。这样的功能在创建插件时非常有用:插件可以调用加载该插件的应用程序中定义的函数。
常规共享库不允许使用未定义的符号。此外,不允许链接包含未定义符号的库。因此,CMake 明确禁止与 MODULE 库链接。因此,CMake 不会为 MODULE 库创建附加文件,这些文件主要用于链接(Windows 上的导入文件、Linux 上的 so 版本和符号链接等)。
插件.h:
// Creates a window.
//
// The function is defined by the application and can be used by plugins.
void CreateWindow(const char* name);
// Initialize the plugin.
//
// Called by the application. Should be defined by the plugin itself.
void InstantiatePlugin(void);
cool_plugin.c:
#include <plugin.h>
void InstantiatePlugin(void)
{
// Just create two windows
CreateWindow("Cool1");
CreateWindow("Cool2");
}
可以使用 MODULE 库使用 CMake 构建此类插件:
# CMakeLists.txt
#
add_library(cool_plugin MODULE cool_plugin.c)
target_include_directories(cool_plugin PRIVATE </path/to/directory/with/plugin.h>)
如果将上述代码中的 MODULE 替换为 SHARED,构建插件将会失败,并出现 未定义的引用/未解析的外部错误。
应用程序本身的代码可能如下所示:
// application.c
#include <plugin.h>
int CreateWindow(const char* name)
{
// ... actually create a window.
}
int main(void)
{
// .. Some initialization
// ... Load the plugin in the platform-specific way (dlopen or LoadLibrary)
void (*instantiate)(void) = ... ; // find function 'InstantiatePlugin' in the plugin
instantiate();
}