Generation and use of Windows and Linux dynamic libraries


The main significance of using dynamic link libraries in c and C++ is:

Saving system resources
When an application needs to link a large number of library functions, using a static link library will result in a large application size, and each application needs to have a complete code library, which will waste system resources. In contrast, the dynamic link library can be shared by multiple applications, thereby avoiding the situation of repeatedly loading codes and reducing the waste of system resources.

Simplify code maintenance
Using a dynamic link library can separate library functions and application program codes, which is beneficial to code maintenance and upgrades. If the library function needs to be updated, only the dynamic link library needs to be replaced, and the application program does not need to be recompiled and deployed. This also makes application development and maintenance more flexible and efficient.

Improving the security of the application
The use of the dynamic link library can prevent the application from being injected with malicious code by exploiting the loopholes of malicious attackers. Since the dynamic link library is an independent binary file, an attacker cannot directly modify its content, thus ensuring the security of the application.

In short, the use of dynamic link libraries can improve system performance and security, simplify code maintenance, and make application development and deployment more flexible and efficient.

Generation and use of Windows dynamic library

Generate dynamic library

The following are the detailed steps to use CMake to build a dynamic library and call it on the Windows system:

Install CMake: Download CMake from the official CMake website, and follow the instructions of the installation wizard to install it.

Create a project directory: Create a project directory on your local disk, and create a folder named "src" under this directory, which will be used to store source code files.

Write the source code: Create a file called "library.cpp" in the "src" folder and write the following code:

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

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

Create a file named "library.h" in the same folder and write the following code:

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

Create a CMakeLists.txt file: Create a file named "CMakeLists.txt" in the project directory and write the following code:

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)

This file tells CMake to compile the source code files into a dynamic library and install it in the specified directory. The "CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS" option here is used to ensure that all symbols can be exported.
"CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS" is a CMake option to export all symbols as public symbols in dynamic libraries on Windows. When this option is "ON", CMake will mark all non-inline, non-template, non-inline command (__inline, __forceinline, __inline__, etc.) symbols as exportable and include them in the generated dynamic library. This is typically used to ensure that all symbols are exported in the dynamic library so that they can be dynamically loaded at runtime. However, using this option may cause some unnecessary symbols to be exported, thereby increasing the size of the dynamic library. Therefore, it is recommended to use this option only when necessary and with caution.

The role of this option is to export all symbols to the dynamic library under the Windows platform, which makes all symbols in the dynamic library available to other programs at runtime. Under the Windows platform, the default behavior of dynamic libraries is to export only explicitly exported symbols into the dynamic library, so if a symbol is not explicitly exported, other programs cannot use this symbol. Using this option can conveniently export all symbols to the dynamic library, so that other programs can use all the functions in the dynamic library. This is very useful for programmers who develop dynamic link libraries, especially when the dynamic link library needs to be widely used by other programs, such as writing plug-ins or developing libraries for other developers to use.

If you do not use the "CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS" option, only the symbols that are explicitly exported through the export symbol list (using __declspec(dllexport)) will be included in the generated dynamic library, while other symbols will not be exported, so that you cannot used by other programs. This can lead to limited functionality of the dynamic library, since other programs cannot use the unexported symbols and thus lose access to all functionality in the dynamic library. Therefore, under the Windows platform, if you want other programs to use all symbols in the dynamic library, it is recommended to use the "CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS" option to export all symbols.

Build the dynamic library: Open a command prompt (or PowerShell), and navigate to the project directory. Enter the following command:

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

This will create a folder called "build" and generate the dynamic library files in it.

call dynamic library

Write the calling code: create a file called "main.cpp" in the "src" folder, and write the following code:

#include "library.h"

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

Create a CMakeLists.txt file: Create a file called "CMakeLists.txt" in the "src" folder and write the following code:

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)


This file tells CMake to create an executable and link it to the dynamic library.

Build the executable: Go back to Command Prompt (or PowerShell) and enter the following command:

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

This will create a folder called "build-app" and build the executable inside it.

Run the application: In Command Prompt (or PowerShell), navigate to the directory where the executable is located and enter the following command:

MyApp.exe

use __declspec(dllexport)

A simple case of using __declspec(dllexport) to export symbols, assuming we want to write a dynamic link library named "mylibrary", which contains two functions add and subtract, which are used to add and subtract two integers respectively. The following are the contents of the header file "mylibrary.h" and the source file "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;
}

In this example, we define a MYLIBRARY_API macro to set export or import keywords depending on whether a dynamic library is currently being compiled. On the Windows platform, we use the __declspec(dllexport) keyword to mark the add and subtract functions as exported functions so that they can be used by other programs in the dynamic library. When compiling a dynamic library, we need to define the MYLIBRARY_EXPORTS macro so that MYLIBRARY_API is set to __declspec(dllexport); and in other programs that use the dynamic library, we need to set MYLIBRARY_API to __declspec(dllimport).

In order to use this dynamic library, we need to add the following to 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()

In this CMakeLists.txt, we first specify the project name and set the C++11 standard. Then, we specify the source file "mylibrary.cpp" as the source file, and use the add_library command to create a dynamic link library named "mylibrary". Finally, we use the target_compile_definitions command to define the MYLIBRARY_EXPORTS macro under the Windows platform in order to set the MYLIBRARY_API macro correctly.

Now, we can use functions from this library, for example:

#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;
}

Generation and use of LINUX dynamic library

show tag

Under the Linux platform, the symbol export and import mechanism of the dynamic link library is different from that of Windows. Linux uses another mechanism, called "symbol versioning," to control the import and export of symbols.

On the Linux platform, you can use the -fvisibility=hidden compiler option to hide the symbol, and only when you explicitly use __attribute__((visibility("default"))) to export the symbol can it be seen by the external linker. For example, when writing a function in a dynamic link library, you can mark it as an exported symbol with:

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

This will tell the linker that my_function is a function that can be accessed from a dynamic link library.

class export symbol

Exported C++ classes can be marked as exported symbols in a similar way. For example:

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

It should be noted that the symbol version control mechanism of Linux is more complicated than that of Windows, involving multiple aspects such as the definition of symbol version, binding and default version. Therefore, when writing a dynamic link library, it is necessary to carefully study and understand relevant documents and specifications to ensure that the export and import of symbols can be performed correctly.

Hide and show example

In order to improve the security and maintainability of the code, it is recommended to use -fvisibility=hidden to hide the symbols when writing the dynamic link library, and only explicitly mark the symbols that need to be exported as visible symbols. This avoids unnecessary symbol exports, reduces the risk of security holes, and improves linker performance. Therefore, under the Linux platform, you can also use __attribute__((visibility("hidden"))) to mark a C++ class as a hidden symbol. For example:

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

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

This will only export the MyExportedClass class, leaving the MyHiddenClass class hidden.

Guess you like

Origin blog.csdn.net/m0_49302377/article/details/130313375
Recommended