编写、生成动态链接库
- 创建头文件 cat.h;
重点:C++ 函数前必须添加 extern “C” , 例如:extern “C” void run();
#ifndef CAT_H_
#define CAT_H_
void say();
void run();
void eat();
#endif
- 创建实现文件 cat.c;
#include <stdio.h>
#include "cat.h"
void say()
{
printf("The cat is saying... ... \n");
}
void run()
{
printf("The cat is running... ... \n");
}
void eat()
{
printf("The cat is eating... ... \n");
}
- 创建文件 makefile;
libcat.so : cat.o
gcc -fPIC -shared cat.c -o libcat.so
cat.o : cat.h
clean :
rm cat.o libcat.so
编写调用程序
创建主程序文件 main.c
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#define DLL_FILE_NAME "./libcat.so"
typedef void (*SAY)();
typedef void (*RUN)();
typedef void (*EAT)();
int main(int argc, char const *argv[])
{
void *handle;
char *error;
SAY s = NULL;
RUN r = NULL;
EAT e = NULL;
handle = dlopen(DLL_FILE_NAME, RTLD_LAZY);
if (!handle) {
fprintf(stderr, "Failed to open library %s error : %s\n", DLL_FILE_NAME, dlerror());
return 1;
}
dlerror();
s = (SAY) dlsym(handle, "say");
if (!s)
{
fprintf(stderr, "> %s\n", dlerror());
return 1;
}
s();
r = (RUN) dlsym(handle, "run");
if (!r)
{
fprintf(stderr, "> %s\n", dlerror());
return 1;
}
r();
e = (EAT) dlsym(handle, "eat");
if (!e)
{
fprintf(stderr, "> %s\n", dlerror());
return 1;
}
e();
dlclose(handle);
return 0;
}
编译、执行
首先,执行命令: make
生成文件 libcat.so
然后,执行命令:gcc -o main main.c -ldl
最后,执行命令:./main
结果:
The cat is saying… …
The cat is running… …
The cat is eating… …
g++(gcc)编译选项
-shared :指定生成动态链接库。
-static :指定生成静态链接库。
-fPIC :表示编译为位置独立的代码,用于编译共享库。目标文件需要创建成位置无关码,念上就是在可执行程序装载它们的时候,它们可以放在可执行程序的内存里的任何地方。
-L. :表示要连接的库所在的目录。
-l:指定链接时需要的动态库。编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.a/.so来确定库的名称。
-Wall :生成所有警告信息。
-ggdb :此选项将尽可能的生成gdb的可以使用的调试信息。
-g :编译器在编译的时候产生调试信息。
-c :只激活预处理、编译和汇编,也就是把程序做成目标文件(.o文件)。
-Wl,options :把参数(options)传递给链接器ld。如果options中间有逗号,就将options分成多个选项,然后传递给链接程序。