您的位置:首页 > 其它

SO文件的编写,编译,使用方法

2016-08-23 09:57 507 查看

(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的方法识别这个函数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: