(1)SO文件简介
linux下的.so文件为共享库,相当于windows下的dll文件。在系统目录/usr/lib/下,我们可以看到很多应用程序库文件(常用的动态链接库和软件包的配置文件)。
(2)SO文件编译方法
A. SO文件没有main
我们首先编写简单的两个函数,然后把它编译成so文件
int max(int a,int b){
if(a>b)
return a;
else
return b;
}
int add(int a,int b){
return a+b;
}
B. makefile文件编写
(1)编译时gcc后加-fPIC,这可以使gcc产生于位置无关的代码;
(2)连接时,使用-shared,指示生成一个共享库文件;
(3)共享库文件一lib开头+扩展名.so;
makefile文件如下:
.SUFFIXES:.c .o
CC=gcc
SRCS=test.c
OBJS=$(SRCS:.c=.o)
EXEC=libtest.so
all:$(OBJS)
$(CC) -shared -o $(EXEC) $(OBJS)
.c.o:
$(CC) -Wall -g -fPIC -o $(@) -c $<
clean:
rm -f $(OBJS)
rm -f core*
make编译链接test.c文件,结果:
xin@xin-Lenovo-V3000:~/code/test1$ ls
makefile test.c test.h
xin@xin-Lenovo-V3000:~/code/test1$ make
gcc -Wall -g -fPIC -o test.o -c test.c
gcc -shared -o libtest.so test.o
xin@xin-Lenovo-V3000:~/code/test1$ ls
libtest.so makefile test.c test.h test.o
生成libtest.so文件。
(3)SO文件使用方法
(1).bash_profile添加export LD_LIBRARY_PATH= LDLIBRARYPATH:.或者将.so文件放入系统目录/usr/lib/(不推荐,这样很可能误删,搞混系统库文件),之所以添加exportLDLIBRARYPATH= LD_LIBRARY_PATH:.是为了,调用.so文件时候于.so文件位置无关。
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
PATH=$PATH:$HOME/bin:.
export PATH
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
一定注意拼写,宝宝曾经犯过一些关于拼写错误,找了很长时间。
然后:wq退出,还要让.bash_profile生效,输入语句:
xin@xin-Lenovo-V3000:~$ . .bash_profile
注意:两个小点之间有一个空格。
(2)在别的c文件(或者cpp)中使用so文件,一定要包含so文件的头文件。
test.h文件:
#ifndef TEST_H
#define TEST_H
#ifdef __cplusplus
extern "C"{
#endif
int max(int a,int b);
int add(int a,int b);
#ifdef __cplusplus
}
#endif
#endif // TEST_H
这里采用了混合编程,否则g++编译会发生错误。
(3).cpp文件为:
#include<stdio.h>
#include<stdlib.h>
#include "test.h"
int main(){
printf("max=%d\n",max(4,5));
printf("add=%d\n",add(4,5));
return 0;
}
(4).cpp的makefile文件编写:
.SUFFIXES:.cpp .o
CC=g++
SRCS=a.cpp
OBJS=$(SRCS:.cpp=.o)
EXEC=a
start:$(OBJS)
$(CC) -o $(EXEC) $(OBJS) -L. -ltest
.cpp.o:
$(CC) -Wall -g -o $(@) -c $<
clean:
rm -f $(OBJS)
rm -f core*
其中:g++链接时-L参数指明so文件存放路径,-l参数指明so文件名。
(CC)−o
(EXEC) $(OBJS) -L. -ltest
-L:在当前路径寻找so文件;
-ltest:意思为链接libtest.so这个库文件;
(5)make结果:
xin@xin-Lenovo-V3000:~$ cd code/test1
xin@xin-Lenovo-V3000:~/code/test1$ make
g++ -Wall -g -o a.o -c a.cpp
g++ -o a a.o -L. -ltest
xin@xin-Lenovo-V3000:~/code/test1$ ls
a a.cpp a.o libtest.so makefile test.c test.h test.o
xin@xin-Lenovo-V3000:~/code/test1$ ./a
max=5
add=9
如果我们.h文件不采用混合编译,而简单的这样写:
#ifndef TEST_H
#define TEST_H
int max(int a,int b);
int add(int a,int b);
#endif // TEST_H
当我们make时候就会:
xin@xin-Lenovo-V3000:~/code/test1$ make
g++ -Wall -g -o a.o -c a.cpp
g++ -o a a.o -L. -ltest
a.o:在函数‘main’中:
/home/xin/code/test1/a.cpp:5:对‘max(int, int)’未定义的引用
/home/xin/code/test1/a.cpp:6:对‘add(int, int)’未定义的引用
collect2: error: ld returned 1 exit status
makefile:7: recipe for target 'start' failed
make: *** [start] Error 1
因为我们编写的.so文件是c编写的,如果cpp文件调用,必须用extern “C”关键字修饰,表示用c的方法识别这个函数。