Windows和Linux动态库的生成及使用


c和C++使用动态链接库的主要意义在于:

节省系统资源
当应用程序需要链接大量的库函数时,使用静态链接库会导致应用程序的体积变得很大,而且每个应用程序都需要拥有一份完整的代码库,这会浪费系统资源。相比之下,动态链接库可以被多个应用程序共享,从而避免了重复加载代码的情况,减少了系统资源的浪费。

简化代码维护
使用动态链接库可以将库函数和应用程序的代码分离开来,这样有利于代码的维护和升级。如果需要更新库函数,只需要替换动态链接库即可,不需要重新编译和部署应用程序。这也使得应用程序的开发和维护变得更加灵活和高效。

提高应用程序的安全性
使用动态链接库可以避免应用程序被恶意攻击者利用漏洞注入恶意代码的情况。由于动态链接库是独立的二进制文件,攻击者无法直接修改其内容,从而保证了应用程序的安全性。

总之,使用动态链接库可以提高系统的性能和安全性,简化代码维护,并使应用程序的开发和部署更加灵活和高效。

Windows动态库的生成及使用

生成动态库

下面是在Windows系统上使用CMake构建动态库并调用它的详细步骤:

安装CMake:在CMake官方网站上下载CMake,并按照安装向导的提示进行安装。

创建项目目录:在本地磁盘上创建一个项目目录,并在该目录下创建一个名为“src”的文件夹,该文件夹将用于存储源代码文件。

编写源代码:在“src”文件夹中创建一个名为“library.cpp”的文件,并编写以下代码:

#include <iostream>
#include "library.h"

void Library::HelloWorld() {
    std::cout << "Hello, World!" << std::endl;
}

在同一文件夹中创建一个名为“library.h”的文件,并编写以下代码:

class Library {
public:
    void HelloWorld();
};

创建CMakeLists.txt文件:在项目目录下创建一个名为“CMakeLists.txt”的文件,并编写以下代码:

cmake_minimum_required(VERSION 3.0)

project(MyLibrary)

set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)

add_library(MyLibrary SHARED library.cpp)

target_include_directories(MyLibrary PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

install(TARGETS MyLibrary DESTINATION lib)
install(FILES library.h DESTINATION include)

此文件告诉CMake将源代码文件编译为动态库,并将其安装在指定目录下。此处的“CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS”选项用于确保所有符号都可以导出。
“CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS” 是一个CMake的选项,用于在Windows上将所有符号导出为动态库中的公共符号。当该选项为“ON”时,CMake会将所有非inline、非template、非内联命令(__inline、__forceinline、__inline__等)的符号标记为可导出,并将它们包含在生成的动态库中。这通常用于确保可以在动态库中导出所有的符号,使得可以在运行时动态加载这些符号。但是,使用这个选项可能会导致一些不必要的符号被导出,从而增加了动态库的大小。因此,建议只在需要时使用该选项,并谨慎使用。

这个选项的作用是在 Windows 平台下将所有符号都导出到动态库中,这使得动态库中的所有符号都可以在运行时被其他程序使用。在 Windows 平台下,动态库的默认行为是仅将显式导出的符号导出到动态库中,因此如果一个符号没有被显式地导出,那么其他程序就不能使用该符号。使用该选项可以方便地将所有符号都导出到动态库中,使得其他程序可以使用动态库中的所有功能。这对于开发动态链接库的程序员非常有用,特别是当动态链接库需要被其他程序广泛使用时,如编写插件或者开发库供其他开发者使用时。

如果不使用"CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS"选项,则只有显式地通过导出符号列表(使用__declspec(dllexport))导出的符号才会被包含在生成的动态库中,而其他符号则不会被导出,从而不能被其他程序使用。这可能会导致动态库的功能受到限制,因为其他程序无法使用未导出的符号,从而无法访问动态库中的所有功能。因此,在 Windows 平台下,如果希望其他程序可以使用动态库中的所有符号,建议使用"CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS"选项来导出所有符号。

构建动态库:打开命令提示符(或PowerShell),并导航到项目目录。输入以下命令:

mkdir build
cd build
cmake ..
cmake --build .

这将创建一个名为“build”的文件夹,并在其中生成动态库文件。

调用动态库

编写调用代码:在“src”文件夹中创建一个名为“main.cpp”的文件,并编写以下代码:

#include "library.h"

int main() {
    Library myLibrary;
    myLibrary.HelloWorld();
    return 0;
}

创建CMakeLists.txt文件:在“src”文件夹中创建一个名为“CMakeLists.txt”的文件,并编写以下代码:

cmake_minimum_required(VERSION 3.0)

project(MyApp)

add_executable(MyApp main.cpp)

target_link_libraries(MyApp PRIVATE MyLibrary)

target_include_directories(MyApp PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

install(TARGETS MyApp DESTINATION bin)


此文件告诉CMake创建一个可执行文件,并链接到动态库文件。

构建可执行文件:回到命令提示符(或PowerShell)并输入以下命令:

cd ..
mkdir build-app
cd build-app
cmake ..
cmake --build .

这将创建一个名为“build-app”的文件夹,并在其中生成可执行文件。

运行应用程序:在命令提示符(或PowerShell)中导航到可执行文件所在的目录,并输入以下命令:

MyApp.exe

使用__declspec(dllexport)

使用__declspec(dllexport)导出符号的简单案例,假设我们要编写一个名为"mylibrary"的动态链接库,其中包含两个函数add和subtract,分别用于将两个整数相加和相减。以下是头文件"mylibrary.h"和源文件"mylibrary.cpp"的内容:

// mylibrary.h
#ifndef MYLIBRARY_H
#define MYLIBRARY_H

#ifdef _WIN32
    #ifdef MYLIBRARY_EXPORTS
        #define MYLIBRARY_API __declspec(dllexport)
    #else
        #define MYLIBRARY_API __declspec(dllimport)
    #endif
#else
    #define MYLIBRARY_API
#endif

MYLIBRARY_API int add(int a, int b);
MYLIBRARY_API int subtract(int a, int b);

#endif  // MYLIBRARY_H

// mylibrary.cpp
#include "mylibrary.h"

MYLIBRARY_API int add(int a, int b)
{
    return a + b;
}

MYLIBRARY_API int subtract(int a, int b)
{
    return a - b;
}

在这个例子中,我们定义了一个MYLIBRARY_API宏,用于根据当前是否正在编译动态库来设置导出或导入关键字。在 Windows 平台下,我们通过__declspec(dllexport)关键字将add和subtract函数标记为导出函数,以便在动态库中可以被其他程序使用。当编译动态库时,我们需要定义MYLIBRARY_EXPORTS宏,以便将MYLIBRARY_API设置为__declspec(dllexport);而在使用动态库的其他程序中,我们需要将MYLIBRARY_API设置为__declspec(dllimport)。

为了使用该动态库,我们需要在CMakeLists.txt中添加以下内容:

# CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(mylibrary)

# Set C++ standard to C++11
set(CMAKE_CXX_STANDARD 11)

# Add source files
set(SOURCES mylibrary.cpp)

# Create shared library
add_library(mylibrary SHARED ${SOURCES})

# Define preprocessor macro for exporting symbols on Windows
if(WIN32)
    target_compile_definitions(mylibrary PRIVATE MYLIBRARY_EXPORTS)
endif()

在这个CMakeLists.txt中,我们首先指定项目名称,并设置了C++11标准。然后,我们将源文件"mylibrary.cpp"指定为源文件,并使用add_library命令创建一个名为"mylibrary"的动态链接库。最后,我们使用target_compile_definitions命令在 Windows 平台下定义MYLIBRARY_EXPORTS宏,以便正确设置MYLIBRARY_API宏。

现在,我们可以使用该库中的函数,例如:

#include <iostream>
#include "mylibrary.h"

int main()
{
    int x = add(3, 4);
    int y = subtract(7, 5);
    std::cout << "3 + 4 = " << x << std::endl;
    std::cout << "7 - 5 = " << y << std::endl;
    return 0;
}

LINUX动态库的生成及使用

显示标记

在 Linux 平台下,动态链接库的符号导出和导入机制与 Windows 有所不同。Linux 使用了另一种机制,称为“符号版本控制”(symbol versioning),来控制符号的导入和导出。

在 Linux 平台下,可以使用-fvisibility=hidden编译选项来将符号隐藏起来,只有显式地使用__attribute__((visibility(“default”)))来导出符号才能被外部链接程序看到。例如,在编写动态链接库中的函数时,可以使用以下方式将其标记为导出符号:

__attribute__((visibility("default"))) int my_function(int arg1, int arg2) {
    // function body here
}

这将告诉链接程序,my_function是一个可以从动态链接库中访问的函数。

类的导出符号

对于导出的 C++ 类,可以使用类似的方式将其标记为导出符号。例如:

class __attribute__((visibility("default"))) MyExportedClass {
public:
    MyExportedClass();
    ~MyExportedClass();
    // class member functions here
};

需要注意的是,Linux 的符号版本控制机制比 Windows 更加复杂,涉及到符号版本的定义、绑定和默认版本等多个方面。因此,在编写动态链接库时,需要仔细研究和理解相关文档和规范,以确保符号的导出和导入能够正确地进行。

隐藏和显示的例子

为了提高代码的安全性和可维护性,建议在编写动态链接库时,使用-fvisibility=hidden将符号隐藏起来,只显式地将需要导出的符号标记为可见符号。这样可以避免不必要的符号导出,减少安全漏洞的风险,并提高链接程序的性能。因此,在 Linux 平台下,也可以将 C++ 类使用__attribute__((visibility(“hidden”)))将其标记为隐藏符号。例如:

class __attribute__((visibility("hidden"))) MyHiddenClass {
public:
    MyHiddenClass();
    ~MyHiddenClass();
    // class member functions here
};

class __attribute__((visibility("default"))) MyExportedClass {
public:
    MyExportedClass();
    ~MyExportedClass();
    // class member functions here
};

这将只导出MyExportedClass类,将MyHiddenClass类隐藏起来。

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZUSTAND

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值