-
linux so 库的生成与调用
2019-09-29 12:02:01本文主要通过导出一个log文件操作的类,来说明linux下so库的生成与调用。先说明一下本文中的几个文件和其作用: 1)ilogfile.h主要用于定义Clogfile类的借口和声明一个C风格的create导出函数,该文件为导出文件,在用...本文主要通过导出一个log文件操作的类,来说明linux下so库的生成与调用。先说明一下本文中的几个文件和其作用:
1)ilogfile.h 主要用于定义Clogfile类的借口和声明一个C风格的create导出函数,该文件为导出文件,在用g++编译的时候需放在最前面。
2)logfile.h 主要定义了Clogfile类的头文件。
3)logfile.cpp 主要提供了Clogfile类的定义。
4)create.cpp 主要定义了一个create函数,在使用时用户可以通过该函数获取一个Clogfile类的对象地址,并将该地址转换为接口对应的Ilogfile类型,这样就对最终用户封闭了Clogfile类。
根据上述1)、2)、3)、4)文件生成一个log.so的动态链接库。
5) main.cpp 该文件定义了一个main函数,在该函数中通过调用生成的动态链接库log.so来实现对Clogfil类的操作。
具体文件的内容如下:
-----------------ilogfile.h文件---------------------------
//ilogfile.h #ifndef _ILOGFILE_H #define _ILOGFILE_H #include<string> using namespace std; class Ilogfile { public: virtual bool open() = 0; virtual void close() = 0; virtual void write(const string& logItemId, const string& logItemContent) = 0; virtual string read(const string& logItemId) = 0; }; extern "C" Ilogfile*create(); #endif//_ILOGFILE_H
-----------------logfile.h文件---------------------------
//logfile.h #include"ilogfile.h" #include<iostream> using namespace std; class Clogfile : public Ilogfile { public: bool open(); void close(); void write(const string& logItemId, const string& logItemContent); string read(const string& logItemId); };
----------------logfile.cpp文件----------------------------
//logfile.cpp #include "logfile.h" bool Clogfile::open() { cout<<"This is function : Clogfile::open()"<<endl; return true; } void Clogfile::close() { cout<<"This is function : Clogfile::close()"<<endl; } void Clogfile::write(const string& logItemId, const string& logItemContent) { cout<<"This is function : Clogfile::write(...)"<<endl; } string Clogfile::read(const string& logItemId) { cout<<"This is function : Clogfile::read(...)"<<endl; }
----------------create.cpp文件----------------------------
//create.cpp #include"logfile.h" Ilogfile* create() { return (Ilogfile*)new Clogfile(); }
---------------main.cpp文件-----------------------------
//main.cpp #include <stdlib.h> #include<stdio.h> #include<dlfcn.h> #include"ilogfile.h" #include<iostream> using namespace std; typedef Ilogfile* (*PFunc)(); int main() { void *SoLib = NULL ; SoLib=dlopen("./log.so",RTLD_LAZY); const char *err = dlerror(); if(err != NULL) { fputs(err, stderr); exit(1); } PFunc pcreate = NULL; pcreate = (PFunc)dlsym(SoLib,"create"); if(NULL == pcreate) { cout<<"Can not get create function from log.so"<<endl; return 0; } Ilogfile* plogfile = (*pcreate)(); plogfile->open(); return 0; }
接下来通过快捷键“alt+Ctrl+t”打开终端命令框,并进入到上述几个文件保存的目录中,然后生成动态库并进行调用,过程如下:
1)生成动态库log.so,命令为:g++ ilogfile.h logfile.h logfile.cpp create.cpp -fPIC -shared -o log.so
注意:上述命令里ilogfile.h为导出文件,要放在第一个位置。
2)编译main.cpp生成调用动态库的main文件,命令为:g++ main.cpp -o main -ldl
3) 执行生成的main文件,命令为:./main
需要注意,在第2)步中需要加上指令-ldl,l是L的小写形式,如果不加上,则会出现下面的错误:
main.cpp:(.text+0x21): undefined reference to `dlopen'
main.cpp:(.text+0x2a): undefined reference to `dlerror'
main.cpp:(.text+0x72): undefined reference to `dlsym' -
linux .so 生成与调用
2015-01-28 21:21:00方法一: 有test.h,test1.c,test2.c,main.c,其中: 1 // main.c 2 #include "test.h" 3 4 void main(){ 5 test1(); 6 test2();...生成.so: gcc test1.c test2.c -fPIC -shared -o libtest.so方法一: 有test.h,test1.c,test2.c,main.c,其中:
1 // main.c 2 #include "test.h" 3 4 void main(){ 5 test1(); 6 test2(); 7 }
生成.so: gcc test1.c test2.c -fPIC -shared -o libtest.so
调用.so: gcc main.c -L. -ltest -o main
export LD_LIBRARY_PATH=/home/linden/projects //LD_LIBRARY_PATH的意思是告诉loader在哪些目录中可以找到共享库. 可以设置多个搜索目录, 这些目录之间用冒号分隔开
./main即可方法二:
1 //test.h 2 3 #include "stdio.h" 4 void test1(); 5 void test2();
1 //test1.c 2 3 #include "stdio.h" 4 void test1(){ 5 printf("this is test11111111...\n"); 6 }
1 //test2.c 2 3 #include "stdio.h" 4 void test2(){ 5 printf("this is test22222222...\n"); 6 }
1 //main.c 2 3 #include "stdio.h" 4 #include "stdlib.h" 5 #include "dlfcn.h" 6 #include "test.h" 7 8 void main(){ 9 void *SoLib; 10 int (*So)(); 11 SoLib = dlopen("./libtest.so",RTLD_LAZY); ////加载libtest.so 12 So = dlsym(SoLib,"test1"); //声名test1方法 13 (*So)(""); //执行test1方法 14 return; 15 }
生成.so文件:gcc test.h test1.c test2.c -fPIC -shared -o libtest.so
调用.so文件:gcc main.c -o test -ldl
-
linux将所有文件生成lst_linux环境生成.so文件
2020-12-20 23:32:39$gcc -c hello.c -o hello.o1....连接成动态库生成动态库用gcc来完成,由于可能存在多个版本,因此通常指定版本号:$gcc -shared -Wl,-soname,libhello.so.1 -o libhello.so.1.0 hello.o另外再建立...$gcc -c hello.c -o hello.o
1.连接成静态库
连接成静态库使用ar命令,其实ar是archive的意思
$ar cqs libhello.a hello.o
2.连接成动态库
生成动态库用gcc来完成,由于可能存在多个版本,因此通常指定版本号:
$gcc -shared -Wl,-soname,libhello.so.1 -o libhello.so.1.0 hello.o
另外再建立两个符号连接:
$ln -s libhello.so.1.0 libhello.so.1
$ln -s libhello.so.1 libhello.so
这样一个libhello的动态连接库就生成了。最重要的是传gcc -shared 参数使其生成是动态库而不是普通执行程序.
-Wl 表示后面的参数也就是-soname,libhello.so.1直接传给连接器ld进行处理。实际上,每一个库都有一个soname,当连接器发现它正 在查找的程序库中有这样一个名称,连接器便会将soname嵌入连结中的二进制文件内,而不是它正在运行的实际文件名,在程序执行期间,程序会查找拥有 soname名字的文件,而不是库的文件名,换句话说,soname是库的区分标志。
这样做的目的主要是允许系统中多个版本的库文件共存,习惯上在命名库文件的时候通常与soname相同
libxxxx.so.major.minor
其中,xxxx是库的名字,major是主版本号,minor 是次版本号
至于头文件的使用 只要.c文件和.h文件在同一目录下就可以直接用#include "your.h" 如果在.c文件的上层目录 那只要做如下修改#include "../your.h" 就能够让你的编译器找到了!
一、创建共享库
1 单独编译SList.cpp,编译时需要传入-fPIC选项,告诉编译器生成位置无关代码.
位置无关代码可以被加载到地址空间的任意位置而不需要修改.
[root@LEE src]# ls
main.cpp SList.cpp SList.h
[root@LEE src]# g++ -fPIC -g -c SList.cpp
2 当链接到库时,为链接器传入-shared选项,把目标文件SList.o链接为共享对象
libSList.so.1.0.1
每个共享库都有一个特定的搜索名(soname).搜索名约定如下:
lib+库名+.so+.版本号
在文件系统中,搜索名是一个指向实名的符号连接.每个共享库也有一个特定的实名,约定如下:
搜索名+.子版本号+.发布号
你可以使用一个特殊的编译器选项-Wl,option,将option传给ld,用逗号分隔多个option,
为了在所有的系统上得到最好结果,链接libSList到标准C++库上
[root@LEE src]# g++ -g -shared -Wl,-soname,libSList.so.1 -o libSList.so.1.0.1 SList.o -lstdc++
[root@LEE src]# ls
libSList.so.1.0.1 main.cpp SList.cpp SList.h SList.o
libSList.so.1是搜索名,libSList.so.1.0.1是实名,SList.o是目标文件(也可以是多个目标文件的列表)
,-lstdc++是库需要访问的库(也可以是库的列表-llibrary,关于此选项参考附录.)
3 创建一个从soname链接到库
[root@LEE src]# ln -fs libSList.so.1.0.1 libSList.so.1
[root@LEE src]# ln -fs libSList.so.1 libSList.so
4 使用-L使链接器在当前目录中查找库,并且使用-lSList告诉它要链接哪个库
[root@LEE src]# g++ -g -c main.cpp -o main.o
[root@LEE src]# g++ -g -o main main.o -L. -lSList
[root@LEE src]# ls
libSList.so libSList.so.1.0.1 main.cpp SList.cpp SList.o
libSList.so.1 main main.o SList.h
5 运行命令
[root@LEE src]# LD_LIBRARY_PATH=$(pwd) ./main [In the same line]
4->17->19->10->23->21->11->20
LD_LIBRARY_PATH
提供用来搜索库的目录路径,以冒号作为间隔.正常情况下它不应该被设置,因为系统文件
/ect/ld.so.conf提供了默认的路径.
二、使用链接库
当运行一个程序时,动态装载器通常在/ect/ld.so.conf.d目录查找程序所需要的库.但是,如果
LD_LIBRARY_PATH 环境变量被设置,它首先扫描在LD_LIBRARY_PATH 中列出的目录.对于上一节5,如果直接运行
命令 ./main,会出现找不到库的现象.如:
[root@LEE src]# ./main
./main: error while loading shared libraries: libSList.so.1: cannot open shared object file: No such file or directory
上述问题的解决方案有两种(我能想到的):
1 如果LD_LIBRARY_PATH 没设定:
拷贝libSList.so到目录 /usr/local/lib (同理也可以拷到/usr/lib下)
[root@LEE src]# cp libSList.so /usr/local/lib
[root@LEE src]# ldconfig /usr/local/lib
[root@LEE src]# ./main
4->17->19->10->23->21->11->20
2 如果LD_LIBRARY_PATH 设定:
编辑.bash_profile文件
添加LD_LIBRARY_PATH:=$LD_LIBRARY_PATH:/path/to/libSList.so(不包括 libSList.so)
执行.bash_profile 文件.
[root@LEE src]# . /root/.bash_profile
[root@LEE src]# ./main
4->17->19->10->23->21->11->20
-
Linux下生成.so文件
2016-07-28 09:47:00linux下的.so文件即Shared Libraries。Shared Library 是程序运行时加载的库文件。当一个shared library 被成功的安装以后,之后启动的所有程序都会自动使用最新的shared library。也就是说,生成一个.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
这个路径中的库文件将被在正常寻找前首先寻找。注意事项
- .so文件(也就是Shared Libraries)必须以lib开头,以.so结尾,比如:libalpha.so。(作为特例,一些最低级的C库并不是以lib开头的)
- 必须将自定义的文件加入到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。调用成功。
-
linux将所有文件生成lst_Linux如何生成.so库文件
2020-12-30 11:40:36$gcc -c hello.c -o hello.o1....连接成动态库生成动态库用gcc来完成,由于可能存在多个版本,因此通常指定版本号:$gcc -shared -Wl,-soname,libhello.so.1 -o libhello.so.1.0 hello.o另外再建立... -
linux so库生成(一)
2015-01-16 12:09:16$gcc -shared -Wl,-soname,libhello.so.1 -o libhello.so.1.0 hello.o 另外再建立两个符号连接: $ln -s libhello.so.1.0 libhello.so.1 $ln -s libhello.so.1 libhello.so 这样一个libhello的动态连接 -
C++Linux生成SO库
2021-03-03 17:40:121.制作so文件:libadd_c.so add.c: int add(int a, int b) { return a + b; } 编译: gcc -shared -fpic -lm -ldl -o libadd_c.so add.c 2.编写测试函数 test.cpp #include <stdio.h> #include <... -
linux下生成so库及调用
2017-07-12 11:35:29tof.h #include "stdio.h" void tof(); tof.cpp #include "tof.h" #include using namespace std; void tof() ...生成so 库 gcc tof.cpp -fPIC -shared -o libtof.so -fPIC -
linux将所有文件生成lst_Linux如何生成.so库文件(转)
2020-12-20 23:32:43$gcc -c hello.c -o hello.o1....连接成动态库生成动态库用gcc来完成,由于可能存在多个版本,因此通常指定版本号:$gcc -shared -Wl,-soname,libhello.so.1 -o libhello.so.1.0 hello.o另外再建立... -
linux下生成和调用SO库文件的程序示例
2010-04-20 22:02:38这是个LINUX下生成SO文件,和调用SO库的程序示例. -
linux下生成.so文件和.a文件
2019-01-23 10:48:37原文链接:... linux下生成.so文件和.a文件 test.h 1 #ifndef _TEST_H_ 2 #define _TEST_H_ 3 4 void TestA(); 5 void TestB(); 6 7 #endif t... -
linux下生成动态链接库so文件
2015-09-29 16:30:11怎样在linux下生成动态链接库即.so文件? 一、 首先需要一个好的编译工具,直接用gcc命令行编译已经不再是一个明智之举了,一个好的带编译工具的环境是很重要的,我选择的是easyeclipse,它集成了CDT,可以很... -
linux下生成ffmpeg的so包用于android开发浅尝
2019-08-13 18:32:31linux下生成ffmpeg的so包用于android开发浅尝 安装linux 下载ndk以及ffmpeg 修改配置文件 生产so包 首先,安装我是在windows里面安装的vwmware,然后安装的ubuntu虚拟机; 安装好以后,首先配置相关软件; //1.... -
linux下生成和调用QT so库
2020-04-09 11:47:42生成动态库 1.创建QT项目,创建C++Liberary 一路next,选取模块的时候按需要选择,默认仅选择QtCore模块 2.在自定义的类中写一个hello()的测试函数 XXX_global.h是所有Library项目都有的...一般会有XXX.so.1.0.... -
linux下生成.so并运行程序加载该.so
2016-10-26 14:33:01此时如果我们想要生成动态库,要做的工作其实非常简单,输入gcc -shared -fPIC -o libtest.so test.c即可。回车后输入ls,我们就可以发现当前目录下面出现了libtest.so文件 在上面的代码当中,我们发现使用到了... -
linux环境生成.so文件
2013-09-06 09:43:00libSList.so.1是搜索名,libSList.so.1.0.1是实名,SList.o是目标文件(也可以是多个目标文件的列表) ,-lstdc++是库需要访问的库(也可以是库的列表-llibrary,关于此选项参考附录.) 3 创建一个从soname链接到库 ... -
java 调用linux C++生成的so文件
2020-06-10 16:30:18public class TestHello { //继承Library,用于加载库文件 --Class mapping public interface CLibrary extends Library { // 加载libhello.so链接库 public String JNA_ImgProcess = "HelloToJava"; public C... -
Linux上生成c/c++ cpp文件的so文件
2019-07-31 22:24:59在linux上生成so文件: 准备.cpp文件和.h文件。cpp文件为源码,包含对导出函数的实现,最好使用c来写,方法上使用 extern "C" 修饰,绝对不可使用__stdcall来修饰,此修饰词为Windows文件的修饰词,生成dll时可以加... -
Linux 生成so库文件并调用
2019-11-05 17:45:46为了不暴露源码,将c文件生成so动态库来给别人调用 记录一下方法 首先简单的创建一些测试文件:test.h a.c b.c c.c 如下: test.h #include <stdio.h> void a(); void b(); void c(); a.c #include "test.h... -
java linux so_Java在linux下调用C/C++生成的so文件
2021-02-12 15:59:31将.c文件编译成.o,再重新转换成.so或者.dll文件 gcc -fPIC -D_REENTRANT -I /usr/lib/jvm/java/include -I /usr/lib/jvm/java/include/linux -c MyJni.c 生成文件:MyJni.o 6. 将.o文件编译成.so文件 gcc -shared ... -
linux 下生成动态库.so并引用
2014-12-20 22:59:24动态库的引入及减少了主代码文件的大小,同时生成的动态库又是动态加载的,只有运行的时候才去加载,linux 下的 动态库 .so 就像windows下的 DLL一样。有关动态库的概念自行上网搜。一下是创建及引用动态库 ... -
linux下生成动态链接库.so
2014-09-16 10:36:04问:我源文件为main.c, x.c, y.c, z.c,... 生成动代连接库,假设名称为libtest.so gcc x.c y.c z.c -fPIC -shared -o libtest.so #2. 将main.c和动态连接库进行连接生成可执行文件 gcc main.c -L. -ltest -o -
2019-11-14 linux生成调用.so文件
2019-12-21 10:15:03文章目录动态链接linux生成.so文件linux使用.so文件静态链接linux生成.a文件linux使用.so文件 动态链接 简单理解就是记录文件的路径,通过路径找到对应文件,文件删除,库则无法使用 优点:不占空间 缺点:效率低 ... -
linux GCC 生成so文件 makefile 编写 Windows代码移植
2020-12-14 17:08:50#elif defined(_WIN32) || defined(WIN32) || defined(WIN32) #ifdef _WIN32 #include #include #else #include #include #include #include #endif 实例 OUTPUTFILE=libPcie55.so all: Pcie55 Pcie55:pkg.o sm4.o ...