链接库
2019-07-10 本文已影响0人
zoant
命名
"lib" + soname + ".so" + 主版本号 + 发行版本号(可选)
注意:有些不以lib开头
简例
/*phello.h*/
extern "C" void ph();
/*phello.cpp*/
#include <stdio.h>
#include "phello.h"
void ph()
{
printf("hello");
}
gcc -shared -fPIC phello.cpp -o libph.so
-shared:这是个动态库
-fPIC:位置无关代码(Position Independent Code)
静态加载
/*main.cpp*/
#include <stdio.h>
#include <phello.h>
int main(int argc, char** argv)
{
ph();
return 0;
}
gcc main.cpp -o main -L./ -lph -I./
-L:动态库目录
-l:动态库
-I:头文件目录
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
环境变量LD_LIBRARY_PATH,从当前目录查找so
./main
执行
动态加载
/*main.cpp*/
#include <stdio.h>
#include <dlfcn.h>
#define DLL_FILE_NAME "./libph.so"
int main(int argc, char** argv)
{
void *handle;
void (*func)();
handle = dlopen(DLL_FILE_NAME, RTLD_NOW);
if (handle == NULL)
{
printf("Failed to open libaray %s error:%s\n", DLL_FILE_NAME, dlerror());
return -1;
}
func = (void (*)())dlsym(handle, "ph");
if (handle == NULL)
{
printf("error:%s\n", dlerror());
return -1;
}
func();
dlclose(handle);
return 0;
}
gcc main.cpp -o main -lph
编译
./main
执行
函数详解
dlopen
打开方式
- RTLD_LAZY:暂缓决定,等有需要时再解出符号
- RTLD_NOW:立即决定,返回前解除所有未决定的符号
- RTLD_GLOBAL:动态库中定义的符号可被其后打开的其它库解析。
- RTLD_LOCAL:默认,与RTLD_GLOBAL相反
dlclose
so打开会有计时器,dlclose相当减一,当为0时自动从内存中卸载
extern “C”
可以修饰函数和变量
表示用c语言风格来编译
这里so的函数必须使用extern “C”修饰,否则dlsym会报错
以为c++为了使用多态,会把函数名和参数联合起来生成一个中间的函数名称
构造和析构
void attribute(constructor) x_init(void)
void attribute(destructor) x_fini(void)
分别在dlopen和dlclose前后被调用
函数名可以随意起
相关命令
ldd ./main
可以查看./main依赖的所有so