1 需求
函数引用方式
场景一:同一个源文件
场景二:不同源文件
- 方式一:函数声明
- 方式二:头文件
场景三:静态链接
场景四:动态链接
场景五:动态加载
场景 | 函数引用特点 | 典型应用场景 | 编译 / 链接命令示例 |
---|---|---|---|
同一个源文件 | 直接调用,可依赖隐式声明(不推荐) | 小型程序 | gcc main.c -o main |
不同源文件 | 通过头文件引入声明 | 模块化项目 | gcc main.c math.c -o main |
静态链接 | 链接时嵌入静态库 | 嵌入式系统、需要独立运行程序 | gcc main.c -L. -lmath -o main |
动态链接 | 运行时加载共享库 | 大型应用程序、共享库重用 | gcc main.c -L. -lmath -o main |
动态加载 | 运行时获取函数地址并调用 | 插件系统、动态扩展功能 | gcc main.c -ldl -o main |
2 接口
3.1 示例
场景一:同一个C文件
main.c
#include <stdio.h>
int add(int x, int y) {
return x + y;
}
int main() {
int z;
z = add(1, 2);
printf("%d\n", z);
return 0;
}
3.2 示例
场景二:不同C文件 - 函数声明
main.c
#include <stdio.h>
int add(int x, int y);
int main() {
int z;
z = add(10, 20);
printf("%d\n", z);
return 0;
}
add.c
int add(int x, int y) {
return x + y;
}
3.3 示例
场景二:不同C文件 - 头文件
main.c
#include <stdio.h>
#include "add.h"
int main() {
int z;
z = add(10, 20);
printf("%d\n", z);
return 0;
}
add.c
#include "add.h"
int add(int x, int y) {
return x + y;
}
add.h
#ifndef UNTITLED_ADD_H
#define UNTITLED_ADD_H
int add(int x, int y);
#endif //UNTITLED_ADD_H
3.3 示例
场景三:静态链接
gcc -c add.c
ar cr libadd.a add.o
gcc -o main main.c libadd.a
3.4 示例
场景四:动态链接
gcc -c add.c
gcc -shared -fPIC -o libadd.so add.o
cp libadd.so /lib
ldconfig -v
gcc -o main main.c libadd.so
3.5 示例
场景五:动态加载
main.c
#include <stdio.h>
#include <dlfcn.h> //实现动态链接需要的库
#include "add.h"
int main(void)
{
int (*add)(); //函数指针!
void *fb = NULL;
char *err = NULL;
fb = dlopen("./libadd.so", RTLD_LAZY);
if(!fb)
{
printf("Failed load library!\n");
}
err = dlerror();
if(err != NULL) {
printf("%s\n", err);
return (-1);
}
add= dlsym(fb, "add");
err = dlerror();
if(err != NULL) {
printf("%s\n", err);
return (-1);
}
printf("2 + 3 = %d\n",(*add)(2,3));
dlclose(fb);
return 0;
}
gcc -c add.c
gcc -shared -fPIC -o libadd.so add.o
gcc -o main main.c -ldl
4 参考资料
……