静态链接库的调用方法
静态链接库的调用涉及库的准备、项目配置和代码编写三个主要环节。下面详细介绍不同平台下的调用方式。
1. Windows平台调用静态库(.lib)
准备工作
- 拥有静态库文件(
mylib.lib
) - 拥有对应的头文件(
mylib.h
)
方法一:通过VS项目设置
- 添加头文件路径:
项目属性 → C/C++ → 常规 → 附加包含目录
- 添加库目录:
项目属性 → 链接器 → 常规 → 附加库目录
- 指定库文件:
项目属性 → 链接器 → 输入 → 附加依赖项 → 添加"mylib.lib"
方法二:代码中直接指定
#pragma comment(lib, "mylib.lib") // 自动链接库文件
#include "mylib.h" // 包含头文件
int main() {
lib_function(); // 调用库函数
return 0;
}
2. Linux/Unix平台调用静态库(.a)
准备工作
- 静态库文件(
libmylib.a
) - 头文件(
mylib.h
)
编译命令
g++ main.cpp -I/path/to/headers -L/path/to/libs -lmylib -o myapp
参数说明:
-I
:指定头文件目录-L
:指定库文件目录-l
:指定库名(去掉lib前缀和.a后缀)
完整示例
假设目录结构:
project/
├── include/
│ └── mylib.h
├── lib/
│ └── libmylib.a
└── src/
└── main.cpp
编译命令:
g++ src/main.cpp -Iinclude -Llib -lmylib -o myapp
3. 跨平台通用方法(CMake)
CMakeLists.txt示例
cmake_minimum_required(VERSION 3.10)
project(MyApp)
# 设置头文件路径
include_directories(include)
# 添加静态库
add_library(mylib STATIC IMPORTED)
set_target_properties(mylib PROPERTIES
IMPORTED_LOCATION "lib/libmylib.a" # Windows用.lib路径
)
# 创建可执行文件
add_executable(myapp src/main.cpp)
# 链接静态库
target_link_libraries(myapp mylib)
4. 静态库调用注意事项
-
符号冲突:
- 当多个静态库包含相同符号时会导致链接错误
- 解决方法:使用命名空间或重命名冲突符号
-
初始化顺序:
- 静态库中的全局对象构造函数调用顺序不确定
- 解决方法:显式初始化或使用单例模式
-
库依赖顺序:
- 链接时库的顺序很重要,被依赖的库应放在后面
- 例如:
g++ main.o -lA -lB
(A依赖B时)
-
调试信息:
- 发布版静态库通常去除了调试信息
- 开发时可链接调试版库(通常带有
d
后缀,如mylibd.lib
)
-
C/C++混合调用:
#ifdef __cplusplus extern "C" { #endif // C函数声明 #ifdef __cplusplus } #endif
5. 静态库调用示例代码
头文件(mylib.h)
#ifndef MYLIB_H
#define MYLIB_H
#ifdef __cplusplus
extern "C" {
#endif
void print_message(const char* msg);
int add_numbers(int a, int b);
#ifdef __cplusplus
}
#endif
#endif
主程序(main.cpp)
#include <iostream>
#include "mylib.h"
int main() {
print_message("Hello from static library!");
std::cout << "3 + 5 = " << add_numbers(3, 5) << std::endl;
return 0;
}
动态链接库(DLL/SO)调用详解
动态链接库的调用分为显式调用和隐式调用两种主要方式,下面详细介绍各平台下的调用方法。
一、Windows平台动态库调用
1. 隐式调用(加载时链接)
特点:
- 需要
.lib
导入库和.dll
文件 - 程序启动时自动加载
步骤:
-
准备文件:
- 头文件(
mylib.h
) - 导入库(
mylib.lib
) - 动态库(
mylib.dll
)
- 头文件(
-
项目配置:
// 方法1:代码中指定 #pragma comment(lib, "mylib.lib") // 方法2:项目属性设置 // 链接器 → 输入 → 附加依赖项:mylib.lib
-
代码中使用:
#include "mylib.h" int main() { library_function(); // 直接调用 return 0; }
-
部署要求:
- 需将.dll文件放在:
- 应用程序目录
- 系统目录
- PATH环境变量包含的目录
- 需将.dll文件放在:
2. 显式调用(运行时链接)
特点:
- 只需
.dll
文件 - 可以动态加载/卸载
示例代码:
#include <windows.h>
#include <iostream>
typedef void (*FuncPtr)(const char*);
int main() {
HINSTANCE hDll = LoadLibrary(TEXT("mylib.dll"));
if (!hDll) {
std::cerr << "无法加载DLL" << std::endl;
return 1;
}
FuncPtr func = (FuncPtr)GetProcAddress(hDll, "exported_function");
if (func) {
func("Hello from DLL!");
} else {
std::cerr << "找不到函数" << std::endl;
}
FreeLibrary(hDll);
return 0;
}
二、Linux/Unix平台动态库调用
1. 隐式调用
编译命令:
g++ main.cpp -Iinclude -Llib -lmylib -o myapp
运行前:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/libs
./myapp
2. 显式调用
示例代码:
#include <dlfcn.h>
#include <iostream>
typedef void (*FuncPtr)(const char*);
int main() {
void* handle = dlopen("libmylib.so", RTLD_LAZY);
if (!handle) {
std::cerr << dlerror() << std::endl;
return 1;
}
FuncPtr func = (FuncPtr)dlsym(handle, "exported_function");
if (func) {
func("Hello from SO!");
} else {
std::cerr << dlerror() << std::endl;
}
dlclose(handle);
return 0;
}
编译时:
g++ main.cpp -ldl -o myapp
三、跨平台封装示例
#ifdef _WIN32
#include <windows.h>
#define LIB_HANDLE HINSTANCE
#define OPEN_LIB(name) LoadLibrary(TEXT(name))
#define GET_FUNC(handle, name) GetProcAddress(handle, name)
#define CLOSE_LIB(handle) FreeLibrary(handle)
#else
#include <dlfcn.h>
#define LIB_HANDLE void*
#define OPEN_LIB(name) dlopen(name, RTLD_LAZY)
#define GET_FUNC(handle, name) dlsym(handle, name)
#define CLOSE_LIB(handle) dlclose(handle)
#endif
int main() {
LIB_HANDLE lib = OPEN_LIB("mylib");
if (!lib) {
#ifdef _WIN32
std::cerr << "加载DLL失败" << std::endl;
#else
std::cerr << dlerror() << std::endl;
#endif
return 1;
}
auto func = (void(*)(const char*))GET_FUNC(lib, "exported_function");
if (func) {
func("Hello Cross-Platform!");
}
CLOSE_LIB(lib);
return 0;
}
四、调用方式对比
特性 | 隐式调用 | 显式调用 |
---|---|---|
加载时机 | 程序启动时 | 运行时按需加载 |
文件依赖 | 需要.lib/.a导入库 | 只需.dll/.so文件 |
性能 | 启动稍慢 | 启动快,但首次调用有延迟 |
灵活性 | 低 | 高(可动态加载/卸载) |
错误处理 | 启动失败直接报错 | 可运行时处理加载错误 |
适用场景 | 核心依赖 | 插件系统/可选功能 |