Linux下生成.so文件

.so文件是什么?

linux下的.so文件即Shared Libraries。Shared Library 是程序运行时加载的库文件。当一个shared library 被成功的安装以后,之后启动的所有程序都会自动使用最新的shared library。也就是说,生成一个.so文件并告诉编译器它的位置之后,所有的需要引入它的程序都可以同时调用它。

使用.so文件有以下这么几个好处:

  • 升级库但是可以继续支持一些程序,这些程序想要使用较老版本的,或者不向后兼容的库。
  • 重写特定的库文件或者甚至可以在执行特定程序时,指定一个库文件的特定函数
  • 做以上这些的时候程序甚至可以正在使用着当前的库文件

每一个shared library都有一个soname、一个real name、一个linker name。

soname有一个前缀lib、自定义的短语、后跟一个.so、还有一个版本号。如:/usr/lib/libreadline.so.3

real name是一个soname的实体,在文件名中包涵了真实的库版本号。real name相比soname添加了一个句点,一个次要版本号,另一个句点,和一个发型版本号。最后一个句点和发行版本号是可选的。次要号码和发行号码支持配置控制,使别人可以明白安装的是哪个确切的版本。

linker name是没有任何版本号的soname。如/usr/lib/libreadline.so。

管理shared libraries的关键就是将这个文件名拆开。当程序内部列出它们需要的shared libraries时,仅仅需要列出soname即可。相反的,当创建一个shared library时,你只需要创建一个特定的文件名(包括详细的版本信息)即可。当你安装了一个新版本的库时,你只需将它安装在一小部分特殊的文件夹中的一个之中,然后运行程序ldconfig。lgconfig将会检查现存的文件,并且创建real name的soname和symbolic link,同时设置好春村文件。缓存文件位于/etc/ld.so.cache。

ldconfig并不设置linker name;通常这是在库安装时干的事,然后linker name作为指向最新soname或者realname的symbolic link被创建。

symbolic link(软连接)是自己指定的。名字如: /usr/lib/libreadline.so.3.0。

linker name就是一个与/usr/lib/libreadline.so.3相关联的symbolic link。

如果以上看不懂的话,是的我也没看懂,只是大体翻译了这篇文章

LD_LIBRARY_PATH
这个路径中的库文件将被在正常寻找前首先寻找。

注意事项

  1. .so文件(也就是Shared Libraries)必须以lib开头,以.so结尾,比如:libalpha.so。(作为特例,一些最低级的C库并不是以lib开头的)
  2. 必须将自定义的文件加入到LD_LIBRARY_PATH中才能运行。

生成并测试.so文件。

aplusb.c

#include <iostream>
#include "aplusb.h"
using namespace std;
int aPlusB(int a, int b)
{
    int c = a + b;
    return c;
} 

aplusb.h

#ifndef APLUSB_H__
#define APLUSB_H__
extern int aPlusB(int a, int b);
#endif

main.c

#include <iostream>
#include "aplusb.h"
using namespace std;
int main(void)
{
    int a = 1;
    int b = 2;
    int c = 0;
    c = aPlusB(a, b);
    cout<<c<<endl;
    return 0;
}
第一步:创建PIC文件

g++ -c -fPIC aplusb.c

pic代码是位置无关代码,程序运行时计算机会找文件中指定的内存地址去读取数据,但是当读取一个库文件时,库本身指定的地址必须是与内存地址无关的。此时生成了aplusb.o。注意-fPIC比-fpic兼容性要高。

-c 为编译和汇编但是不链接。

生成的.o文件为机器码。

第二步:用第一步生成的文件去创建.so文件。

g++ -shared -o libaplusb.so aplusb.o

第三步:链接

g++ -L/home/lee/JNI -o main main.c -laplusb

第四步: 保证运行时可以调用

$ export LD_LIBRARY_PATH=/home/lee/JNI:$LD_LIBRARY_PATH

至此

第五部:运行

lee@lee-computer:~/JNI$ ./main
3

结果为3。调用成功。

### 创建 `.so` 动态链接库 #### 准备源代码文件 为了创建一个动态链接库,首先需要准备一些C或C++源代码文件。假设有一个简单的函数 `add.c`: ```c // add.c int add(int a, int b) { return a + b; } ``` #### 编写 Makefile 编写一个合适的Makefile来简化编译过程是非常有帮助的。下面是一个用于生成`.so`文件的简单Makefile例子。 ```makefile # Makefile CC=gcc CFLAGS=-fPIC -Wall LDFLAGS= LIBRARY_NAME=mylib SONAME=$(LIBRARY_NAME).so OBJECT_FILES=add.o all: $(SONAME) $(SONAME): $(OBJECT_FILES) $(CC) -o $@ clean: rm -rf *.o $(SONAME) ``` 此Makefile定义了一系列变量并指定了构建规则。其中 `-fPIC` 参数告诉GCC生成位置无关代码 (Position Independent Code),这对于共享库来说非常重要[^1]。 #### 使用命令行手动编译 如果不希望通过Makefile自动化流程,则可以直接使用gcc命令来进行编译操作: ```bash gcc -fPIC -c add.c -o add.o gcc -shared -o libmylib.so add.o ``` 第一条指令编译源码成目标文件;第二条则把目标文件打包成为共享对象(`.so`)文件[^2]。 #### 验证和测试新创建的动态库 一旦成功创建了`.so`文件,在实际应用前还需要验证其可用性和正确性。可以通过编写一个小的应用程序来调用该库中的功能进行测试。 例如,创建名为test_add.c 的测试程序如下所示: ```c #include <stdio.h> extern int add(int, int); int main() { printf("Result of adding 3 and 5 is %d\n", add(3, 5)); return 0; } ``` 接着修改环境变量以便能够找到自定义路径下的`.so`文件,并尝试运行上述测试案例: ```bash export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/your/library/ gcc test_add.c -lmylib -o test_add ./test_add ``` 这将打印出两个数相加的结果作为输出,证明已经正确设置了动态链接库[^3]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值