一、动态库
纯 C 情况下
-
add.c 文件
/* add.c */ #include "add.h" int add(int a, int b) { return a + b; }
-
add.h 文件
/* add.h */ #pragma once int add(int a, int b);
-
main.c 文件
/* main.c */ #include <stdio.h> #include "add.h" int main() { printf("call add: %d\n", add(1, 2) ); return 0; }
-
Makefile 文件
# 添加动态运行库环境 export LD_LIBRARY_PATH := $(LD_LIBRARY_PATH):$(shell pwd) build: # 使用源文件生成 so 库 gcc add.c -fPIC -shared -o libadd.so # 使用目标文件生成 so 库 # gcc -shared -fPIC test.o -o libtest.so # 编译测试程序, -L指定库文件的路径, -l指定库文件 gcc main.c -L./ -ladd run: ./a.out
-
运行结果
$ make && make run gcc add.c -fPIC -shared -o libadd.so gcc main.c -L./ -ladd ./a.out call add: 3
C 和 C++ 都能使用
只有下列文件更改
-
add.h 文件
#pragma once #ifdef __cplusplus extern "C" { #endif int add(int a, int b); #ifdef __cplusplus } #endif
-
Makefile 文件
# 添加动态运行库环境 export LD_LIBRARY_PATH := $(LD_LIBRARY_PATH):$(shell pwd) build: # 使用源文件生成 so 库 gcc add.c -fPIC -shared -o libadd.so # 使用目标文件生成 so 库 # gcc -shared -fPIC test.o -o libtest.so # 编译测试程序, 这次更改成 g++ g++ main.c -L./ -ladd run: ./a.out
-
运行结果
$ make && make run gcc add.c -fPIC -shared -o libadd.so g++ main.c -L./ -ladd ./a.out call add: 3
说明:
-fPIC
作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。#ifdef __cplusplus
会判断当前编译环境是 C 还是 C++, 当编译环境是 C++ 时, extern “C” 语法生效, 该语法告诉 C++ 编译器目标代码是 C 的, 应该使用 C 的形式去执行. 如果是 C 环境#ifdef __cplusplus
为 false, 这时就和上面纯 C 情况下一样了。因此稍微更改头文件就后 C 和 C++ 代码都能调用该动态库了。
二、静态库
相对 C 和 C++ 都能使用
一节, 只更改了编译方式, Makefile 文件如下
-
Makefile 文件
build: gcc -c add.c -o add.o ar -crv libadd.a add.o g++ main.c -L./ -ladd run: ./a.out
-
运行结果
$ make && make run gcc -c add.c -o add.o ar -crv libadd.a add.o r - add.o g++ main.c -L./ -ladd ./a.out call add: 3
说明:因为静态链接库是在编译时就添加到程序中,因此不需要再对运行环境进行设置了。