如何在不同操作系统上使用C++静态库和动态库?

一、Windows 系统(Visual Studio/MinGW)

1. 静态库(.lib)

(1)创建静态库(Visual Studio)

  • 新建项目 → 选择「静态库(Static Library)」;
  • 编写库代码(如math.cpp),编译后生成math.lib(默认在Debug/Release目录)。

(2)使用静态库(Visual Studio)

  • 项目右键 →「属性」→「链接器」→「输入」→「附加依赖项」添加math.lib
  • 或代码中通过#pragma comment(lib, "math.lib")引入;
  • 包含库的头文件(如math.h),直接调用函数。

(3)MinGW 创建 / 使用静态库

bash
 
运行
# 创建:编译为目标文件后打包
g++ -c math.cpp -o math.o
ar rcs libmath.a math.o  # 生成libmath.a

# 使用:编译时链接库
g++ main.cpp -o main -L. -lmath  # -L指定路径,-lmath对应libmath.a
 

2. 动态库(.dll + .lib 导入库)

(1)创建动态库(Visual Studio)

  • 新建项目 → 选择「动态链接库(DLL)」;
  • 导出函数需加__declspec(dllexport)
    cpp
     
    运行
     
    // math.h
    #ifdef MATH_EXPORTS
    #define MATH_API __declspec(dllexport)
    #else
    #define MATH_API __declspec(dllimport)
    #endif
    MATH_API int add(int a, int b);
  • 编译生成math.dllmath.lib(导入库)。

(2)使用动态库(Visual Studio)

  • 同静态库:链接math.lib,将math.dll放入可执行文件目录;
  • 运行时需确保math.dll存在(或放入系统System32目录)。

(3)MinGW 创建 / 使用动态库

bash
 
运行
 
# 创建:生成动态库和导入库
g++ -shared -o math.dll math.cpp -Wl,--out-implib=libmath.dll.a

# 使用:链接导入库,运行时依赖math.dll
g++ main.cpp -o main -L. -lmath.dll.a
 

二、Linux 系统(GCC/G++)

1. 静态库(.a)

bash
 
运行
 
# 创建:编译目标文件后打包
g++ -c math.cpp -o math.o
ar rcs libmath.a math.o  # ar工具打包

# 使用:编译时链接库
g++ main.cpp -o main -L. -lmath  # -lmath自动匹配libmath.a
 

2. 动态库(.so)

bash
 
运行
# 创建:生成位置无关代码(-fPIC)+ 动态库
g++ -fPIC -c math.cpp -o math.o
g++ -shared -o libmath.so math.o

# 使用:编译链接库,运行时需找到.so文件
g++ main.cpp -o main -L. -lmath

# 解决运行时库加载问题:
# 方法1:设置环境变量
export LD_LIBRARY_PATH=./:$LD_LIBRARY_PATH
./main

# 方法2:将库放入系统路径(如/usr/lib)
sudo cp libmath.so /usr/lib
ldconfig  # 更新库缓存
 

三、macOS 系统(Clang/G++)

1. 静态库(.a)

bash
 
运行
# 创建与使用同Linux
g++ -c math.cpp -o math.o
ar rcs libmath.a math.o
g++ main.cpp -o main -L. -lmath
 

2. 动态库(.dylib/.so)

bash
 
运行
# 创建:生成.dylib(macOS特有)或.so(兼容Linux)
g++ -fPIC -c math.cpp -o math.o
g++ -shared -o libmath.dylib math.o  # 生成dylib
# 或生成so:g++ -shared -o libmath.so math.o

# 使用:编译链接,运行时指定库路径
g++ main.cpp -o main -L. -lmath

# 运行时加载:
# 方法1:设置DYLD_LIBRARY_PATH
export DYLD_LIBRARY_PATH=./:$DYLD_LIBRARY_PATH
./main

# 方法2:编译时指定rpath(嵌入可执行文件)
g++ main.cpp -o main -L. -lmath -Wl,-rpath,@executable_path/
 

四、跨平台注意事项

  1. 命名规则差异
    • Windows:静态库 / 导入库为xxx.lib,动态库为xxx.dll
    • Linux/macOS:静态库为libxxx.a,动态库为libxxx.so(Linux)/libxxx.dylib(macOS)。
  2. 动态库加载机制
    • Windows:通过LoadLibrary手动加载(动态调用);
    • Linux/macOS:通过dlopen/dlsym手动加载(需链接-ldl)。
  3. 兼容性
    • 静态库需与目标系统编译器匹配(如 Windows 的 MSVC 静态库不能在 MinGW 中使用);
    • 动态库需关注 ABI 兼容性(如 GCC 版本、C++ 标准库版本)。

五、跨平台调用示例(手动加载动态库)

1. Windows(动态加载 DLL)

cpp
 
运行
#include <windows.h>
#include <iostream>

typedef int (*AddFunc)(int, int);  // 函数指针类型

int main() {
    HMODULE hDll = LoadLibrary("math.dll");
    if (hDll) {
        AddFunc add = (AddFunc)GetProcAddress(hDll, "add");
        if (add) std::cout << add(3,2) << std::endl;
        FreeLibrary(hDll);
    }
    return 0;
}
 

2. Linux/macOS(动态加载 SO/DYLIB)

cpp
 
运行
 
#include <dlfcn.h>
#include <iostream>

typedef int (*AddFunc)(int, int);

int main() {
    void* handle = dlopen("./libmath.so", RTLD_LAZY);  // macOS用libmath.dylib
    if (handle) {
        AddFunc add = (AddFunc)dlsym(handle, "add");
        if (add) std::cout << add(3,2) << std::endl;
        dlclose(handle);
    }
    return 0;
}

// 编译:g++ main.cpp -o main -ldl
posted @ 2025-12-04 10:53  小java  阅读(2)  评论(0)    收藏  举报