模块和共享库之间的区别?

问题描述 投票:0回答:4

标题大部分都涵盖了,模块和共享库有什么区别?我刚刚在 CMake 的

add_library
命令中发现了这种区别,他们说:

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

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

module linker shared-libraries cmake
4个回答
44
投票

不同之处在于,您可以使用链接器链接到共享库,但不能使用链接器链接到模块。在一些平台上。

所以...为了完全跨平台并在 CMake 工作的任何地方工作,你永远不应该这样做:

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

公平地说,在 Windows 上,它们都只是 dll,因此这段代码实际上可能有效。但是当你把它带到一个无法链接到模块的平台时,你会遇到错误。

底线:如果需要链接到库,请使用 SHARED。如果您保证该库将“仅”被动态加载,那么使用模块是安全的。 (也许更好的是帮助检测是否有人确实尝试链接到它......)


12
投票


7
投票

..._OUTPUT_DIRECTORY

..._OUTPUT_NAME
 的处理方式:

模块库始终被视为库目标。对于非 DLL 平台,共享库被视为库目标。对于 DLL 平台,共享库的 DLL 部分被视为运行时目标,相应的导入库被视为存档目标。包括 Cygwin 在内的所有基于 Windows 的系统都是 DLL 平台。

例如,这意味着如果您在 Windows 上编译
SHARED

库,

LIBRARY_OUTPUT_DIRECTORY
将被忽略,因为它会查看
ARCHIVE_OUTPUT_DIRECTORY
RUNTIME_OUTPUT_DIRECTORY
    


0
投票
符号

(函数和变量),这些符号在库中未定义(并且未在与其链接的库中定义)。这样的功能在创建插件时非常有用:插件可以调用加载该插件的应用程序中定义的函数。

常规共享库不允许使用未定义的符号。

此外,不允许链接包含未定义符号的库。因此,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(); }
    
© www.soinside.com 2019 - 2024. All rights reserved.