一、引用资料
.c的文件 C语言源代码文件;
.a的文件 由目标文件构成的档案库文件;
.C,.cc或.cxx 的文件 C++源代码文件且必须要经过预处理;
.h的文件 程序所包含的头文件;
.i 的文件 C源代码文件且不应该对其执行预处理;
.ii的文件 C++源代码文件且不应该对其执行预处理;
.m的文件 Objective-C源代码文件;
.mm的文件 Objective-C++源代码文件;
.o的文件 编译后的目标文件;
.s的文件 汇编语言源代码文件;
.S的文件 经过预编译的汇编语言源代码文件。
cmake编译c++动态库so:https://blog.csdn.net/weixin_39536806/article/details/112519164
cmake另一种动态库生成:https://tashaxing.blog.csdn.net/article/
Windows10参考:https://blog.csdn.net/a7055117a/category_3152877.html
https://blog.csdn.net/a7055117a/c.html
ubuntu:Linux下C++编译生成自定义静态库/动态库
ar -x libauthoal.a
gcc -shared *.o -o test.so
编译动态库:GCC编译器,静态库,动态库
动态库又称为共享库或者动态链接库,现代程序中大量地使用动态链接库。例如,Windows 环境中的dll文件和Linux环境下的 so文件。动态库是在程序启动时被装载的。当一个程序装载了一个动态库后,其他应用程序仍然可以装载同一个动态库。
使用 dlopen() 调用动态库SO
https://www.ibm.com/docs/en/zos/2.1.0?topic=functions-dlopen-gain-access-dynamic-link-library
采用dlopen、dlsym、dlclose加载动态链接库【总结】
https://tldp.org/HOWTO/Program-Library-HOWTO/dl-libraries.html
二、如何制作插件dlopen?
动态库,如/usr/lib/system/libsystem_c.dylib,通常在程序运行之前加载。MacOS 的execve系统调用知道如何从 Mach-O 文件中提取对动态库的引用,并在继续之前将它们加载到内存中。但是动态库也可以在运行时显式加载。为了显式加载动态库,我们使用dlfcn.h(“动态加载函数”?)API。这就是“插件”的工作方式:插件是一个动态库!
提供的三个函数dlfcn.h是dlopen、dlclose和dlsym。该dlopen函数将动态库从文件加载到内存中。从内存中dlclose卸载它。在这两者之间,我们使用dlsym提取库中符号的引用。这些符号使我们可以访问库中的函数和其他内容。
这是一个例子。我们有main.c我们的主程序和plugin.c我们的插件。主程序希望插件定义plugin_func,这是一个不带参数并返回int. 主程序加载插件,调用该函数,然后退出。
// main.c
#include <dlfcn.h>
#include <stdio.h>
typedef int plugin_func();
int main() {
void* handle = dlopen("plugin.so", RTLD_LAZY);
if (handle == NULL) {
fprintf(stderr, "Could not open plugin: %s\n", dlerror());
return 1;
}
plugin_func* f = dlsym(handle, "plugin_func");
if (f == NULL) {
fprintf(stderr, "Could not find plugin_func: %s\n", dlerror());
return 1;
}
printf("Calling plugin\n");
int ret = f();
printf("Plugin returned %d\n", ret);
if (dlclose(handle) != 0) {
fprintf(stderr, "Could not close plugin: %s\n", dlerror());
return 1;
}
return 0;
}
// plugin.c
#include <stdio.h>
int plugin_func(void) {
printf("Hello from the plugin!\n");
return 42;
}
我们用 编译插件-shared,并将编译后的对象放在plugin.so(“共享库”)。
$ clang -shared -o plugin.so plugin.c
$ clang main.c
$ ./a.out
Calling plugin
Hello from the plugin!
Plugin returned 42
三、dlopen()函数详解动态库
参考:
https://blog.csdn.net/zhengqijun_/article/details/72540878
https://developpaper.com/loading-dynamic-libraries-using-dlopen/
通过一个例子来讲解dlopen系列函数的使用和操作。
主程序:
#include <stdlib.h>
#include <dlfcn.h>
#include <stdio.h>
//申明结构体
typedef struct __test {
int i;
void (* echo_fun)(struct __test *p);
}Test;
//供动态库使用的注册函数
void __register(Test *p) {
p->i = 1;
p->echo_fun(p);
}
int main(void) {
void *handle = NULL;
char *myso = "./mylib.so";
if((handle = dlopen(myso, RTLD_NOW)) == NULL) {
printf("dlopen - %sn", dlerror());
exit(-1);
}
return 0;
}
动态库:
#include <stdio.h>
#include <stdlib.h>
//申明结构体类型
typedef struct __test {
int i;
void (*echo_fun)(struct __test *p);
}Test;
//申明注册函数原型
void __register(Test *p);
static void __printf(Test *p) {
printf("i = %dn", p->i);
}
//动态库申请一个全局变量空间
//这种 ".成员"的赋值方式为c99标准
static Test config = {
.i = 0,
.echo_fun = __printf,
};
//加载动态库的自动初始化函数
void _init(void) {
printf("initn");
//调用主程序的注册函数
__register(&config);
}
主程序编译:gcc test.c -ldl -rdynamic
动态库编译:gcc -shared -fPIC -nostartfiles -o mylib.so mylib.c
其他代码参考:c++较好的案例
https://github.com/xbanks/dynamic-loading-example可以在运行时从中导入函数的示例库:
//文件:greetings.cpp
#include
< iostream > extern
" C " { void
say_hello ( ) {
std::cout << " Hello world? \n " ;
} void say_good_evening () {
std::cout << " konbanwa! \n " ;
}
}
从上面的代码中得到的要点是extern "C"包装我们想要公开的函数。这是因为我们稍后将使用的工具需要 C 命名约定,并且由于 c++ 使用它的名称修饰做了一些有趣的事情,所以我们需要使用 C 命名约定导出这些函数。
这样做的一个副作用是我们不能在我们的extern块中重载函数,因为导出的符号名称将是相同的,因此会发生冲突。