me
me copied to clipboard
学习 C++ (Part 9: dylib 运行时加载)
使用一个dylib通常有2个方式,多数会采用编译时绑定,在做plugin的时候也会用到运行时链接。
在没有debug信息的时候,我们只能通过nm
从dylib或so中获取symbols, 但无法获取完整的函数签名,所以如果在编译时就需要有header配合,在运行时就需要有对应的函数签名。
➜ file libcalc.dylib
libcalc.dylib: Mach-O 64-bit dynamically linked shared library arm64
➜ size libcalc.dylib
text data bss dec hex filename
104 0 0 104 68 libcalc.dylib
➜ gobjdump -x libcalc.dylib
libcalc.dylib: file format mach-o-arm64
libcalc.dylib
architecture: aarch64, flags 0x00000050:
HAS_SYMS, DYNAMIC
start address 0x0000000000000000
MACH-O header:
magic: 0xfeedfacf
cputype: 0x100000c (ARM64)
cpusubtype: 0 (ARM64_ALL)
filetype: 0x6
ncmds: 0xe
sizeocmds: 0x298
flags: 0x100085
version: 2
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000020 0000000000003f98 0000000000003f98 00003f98 2**2
CONTENTS, ALLOC, LOAD, CODE
1 __TEXT.__unwind_info 00000048 0000000000003fb8 0000000000003fb8 00003fb8 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
SYMBOL TABLE:
0000000000003f98 g 0f SECT 01 0000 [.text] _add
➜ nm libcalc.dylib
0000000000003f98 T _add
然后我们就可以通过dlopen, dlsym, dlclose操作:
#include <dlfcn.h>
#include <mach-o/dyld.h>
#include <stdio.h>
typedef int (*add_func_pointer)(int, int);
int main(int args, char *argv[]) {
char *calc_dylib_path = "./libcalc.dylib";
printf("%s\n", calc_dylib_path);
void *module = dlopen(calc_dylib_path, RTLD_LAZY);
if (module == NULL) {
printf("open dylib failed. (code=%s)\n", dlerror());
}
add_func_pointer add_func = dlsym(module, "add");
if (add_func) {
int sum = add_func(2, 7);
printf("2+7=%d\n", sum);
}
dlclose(module);
return 0;
}
obs的整个plugin体系就是通过dlopen来实现的。