精华内容
下载资源
问答
  • Linux编译动态链接库与使用详解

    千次阅读 2016-08-12 15:55:03
    linux的简介两种 静态 动态库 区别:在于代码被载入的时刻不同。静态的代码在编译过程中已经被载入可执行程序,因此体积较大。共享的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单的引用...

    linux下库的简介

    两种库

    1. 静态库
    2. 动态库
      区别:在于代码被载入的时刻不同。静态库的代码在编译过程中已经被载入可执行程序,因此体积较大。共享库的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单的引用,因此代码体积较小

    库的存储位置和命名规范

    存储:一般放在/usr/lib和/lib下
    命名规范
    1. 静态库的名字一般为libxxxx.a,其中xxxx是该lib的名称
    2. 动态库的名字一般为libxxxx.so.major.minor,xxxx是该动态库的名称,major是主版本号, minor是副版本号

    查看一个可执行程序依赖哪些库
    ldd命令可以查看一个可执行程序依赖的共享库

    在新安装一个库之后如何让系统能够找到他
    如果安装在/lib或者/usr/lib下,那么ld默认能够找到,无需其他操作。
    如果安装在其他目录,需要将其添加到/etc/ld.so.cache文件中,步骤如下
    1. 编辑/etc/ld.so.conf文件,加入库文件所在目录的路径
    2. 运行ldconfig,该命令会重建/etc/ld.so.cache文件

    编写动态链接库

    头文件so.h

    #ifndef  SO_H
    #define  SO_H
    
    int add(int a, int b);
    
    
    #endif  /*SO_H*/

    实现文件so.c

    #include "so.h"
    
    int add(int a, int b)
    {
        return a + b;
    }

    编译动态链接库

    gcc -fPIC -c so.c //生成so.o
    gcc -shared -o libtest.so so.o
    (上面两行可以整合成一行:gcc so.c -fPIC -shared -o libtest.so)

    1. -fpic 使输出的对象模块是按照可重定位地址方式生成的(即与位置无关)。
    2. -shared指定把对应的源文件生成对应的动态链接库文件libtest.so文件
      通过nm -g libtest.so可以看到,导出符号表中已经有add这个符号了:
    $ nm -g libtest.so 
    0000000000000670 T add
    0000000000201030 B __bss_start
                     w __cxa_finalize@@GLIBC_2.2.5
    0000000000201030 D _edata
    0000000000201038 B _end
    0000000000000684 T _fini
                     w __gmon_start__
    0000000000000540 T _init
                     w _ITM_deregisterTMCloneTable
                     w _ITM_registerTMCloneTable
                     w _Jv_RegisterClasses

    使用动态库

    1. 隐式链接(编译时链接)
      编写主程序main.c:
    #include <stdio.h>
    #include "so.h"
    
    int main(int argc, char *argv[])
    {
        printf("%d\n", add(1, 2));
        return 0;
    }

    使用gcc main.c -L. -ltest -o test进行编译。

    • -L:添加库文件的搜索路径
    • -l:指定需要链接的库。该名称是处在头lib和后缀.so中的名称,如上动态库libtest.so的l参数为-l test

    此时通过readelf test -d已经能看到生成的可执行文件test的Dynamic section里依赖libtest.so了

    $ readelf test -d
    
    Dynamic section at offset 0xe18 contains 25 entries:
      Tag        Type                         Name/Value
     0x0000000000000001 (NEEDED)             Shared library: [libtest.so]
     0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
    ......

    dynamic symbols中也有一个undefined symbol(add)

    $ nm -D test 
                     U add
    0000000000601048 B __bss_start
    0000000000601048 D _edata
    0000000000601050 B _end
    00000000004007b4 T _fini
                     w __gmon_start__
    0000000000400578 T _init
                     w _ITM_deregisterTMCloneTable
                     w _ITM_registerTMCloneTable
                     w _Jv_RegisterClasses
                     U __libc_start_main
                     U printf

    在执行隐式链接的程序之前要注意设置LD_LIBRARY_PATH环境变量,或者把前面生成的libtest.so复制到系统路径下,否则会找不到动态库。

    $ ./test 
    ./test: error while loading shared libraries: libtest.so: cannot open shared object file: No such file or directory
    
    $ export LD_LIBRARY_PATH=.
    
    $ ./test 
    3
    1. 显式链接(运行时链接)
      编写主程序dyn_main.c
    #include <stdio.h>
    #include <dlfcn.h>
    
    int main(int argc, char *argv[])
    {
        void *dl = NULL;
        int (*add)(int a, int b);
        dl = dlopen( "./libtest.so", RTLD_LAZY);
        if( dl == NULL )
        {
            printf("so loading error.\n");
            return 1;
        }
        add = (int(*)(int, int))dlsym(dl, "add");
        if( dlerror() != NULL )
        {
            printf("fun load error.\n");
            return 1;
        }
        printf("%d\n", add(1, 2));
        return 0;
    }

    使用gcc dyn_main.c -ldl -o dyn_test编译。

    这时通过readelf dyn_test -d可以发现,dyn_test不依赖libtest.so:

    $ readelf dyn_test -d
    
    Dynamic section at offset 0xe18 contains 25 entries:
      Tag        Type                         Name/Value
     0x0000000000000001 (NEEDED)             Shared library: [libdl.so.2]
     0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
    ......

    dyn_test的dynamic symbols中也没有add:

    $ nm -D dyn_test 
                     U dlerror
                     U dlopen
                     U dlsym
                     w __gmon_start__
                     w _ITM_deregisterTMCloneTable
                     w _ITM_registerTMCloneTable
                     w _Jv_RegisterClasses
                     U __libc_start_main
                     U printf
                     U puts

    运行程序也不需要设置LD_LIBRARY_PATH环境变量

    $ ./dyn_test 
    3

    参考资料
    Linux下编译链接动态库

    展开全文
  • 主要介绍了解决Linux程序编译链接动态库版本的相关问题,文中给出了详细的介绍和示例代码,相信对大家具有一定的参考借鉴价值,有需要的朋友们下面来一起看看吧。
  • LINUX下简单的编译 和使用动态链接库
  • YOLO动态链接库编译和使用 - weixinhum - CSDN博客,YOLO动态链接库编译和使用 - weixinhum - CSDN博客,YOLO动态链接库编译和使用 - weixinhum - CSDN博客
  • 我们知道gcc是一个强大的编译器,很多Linux下的GNU工具都是用C语言写的,并且用gcc编译的,那么gcc的编译过程是怎样的呢,先来看一个总的流程图,我自己简单画的,凑合着看 1首先是源文件经过预加载变成了.i结尾的...

    一 gcc编译过程 
    我们知道gcc是一个强大的编译器,很多Linux下的GNU工具都是用C语言写的,并且用gcc编译的,那么gcc的编译过程是怎样的呢,先来看一个总的流程图,我自己简单画的,凑合着看 
    Linux下GCC编译过程及静态链接库和动态链接库 
    1首先是源文件经过预加载变成了.i结尾的文件,可以通过-E这个参数来生成这个中间文件,这里主要是把一些include的头文件和一些宏定义,放到源文件中。 
    2从预加载的文件经过编译就会变成汇编语言的文件,这一步可以通过-S这个参数来生成这个中间文件 
    3从汇编语言的文件通过汇编,就会变成目标代码.o的文件,这一步可以通过-C这个参数来生成这个中间文件 
    4最后经过链接,生成最终的可执行文件 
    可能这样说比较难懂,我们通过一个例子来说明下: 
    我新建了一个hello.c的文件 
    Linux下GCC编译过程及静态链接库和动态链接库 
    然后我先生成.i结尾的预加载文件 
    gcc -E hello.c -o hello.i 
    Linux下GCC编译过程及静态链接库和动态链接库 
    我们看到这个文件生成了,我们看一下这个文件的内容 
    Linux下GCC编译过程及静态链接库和动态链接库 
    大家会发现这个文件的内容非常多,但是最后是我们本来的代码,上面的代码都是头文件和一些宏的内容,全加载进来了 
    下面我们通过编译生成汇编文件.s 
    gcc -S hello.i -o hello.s 
    Linux下GCC编译过程及静态链接库和动态链接库 
    然后我们看一下这个hello.s 
    Linux下GCC编译过程及静态链接库和动态链接库 
    看到了我们熟悉的汇编语言 
    我们继续,经过汇编器,生成.o的目标文件 
    gcc -c hello.s -o hello.o 
    Linux下GCC编译过程及静态链接库和动态链接库 
    依然来看下内容 
    Linux下GCC编译过程及静态链接库和动态链接库 
    看到了一堆二进制的感觉 
    最后通过链接器,生成可执行文件 
    gcc hello.o -o hello 
    然后执行 
    Linux下GCC编译过程及静态链接库和动态链接库 
    当然如果你不想做这么多步骤,直接gcc hello.c -o hello即可完成上面所有的步骤了。

    二 静态链接库和动态链接库 
    静态链接库就是在程序编译的时候就被加载进来,这样的可执行文件会比较大一些,还不能共享 
    动态链接库是在程序执行的时候加载,可共享 
    看下面一个例子 
    Linux下GCC编译过程及静态链接库和动态链接库 
    现在有这么三个文件 
    Linux下GCC编译过程及静态链接库和动态链接库 
    Linux下GCC编译过程及静态链接库和动态链接库 
    Linux下GCC编译过程及静态链接库和动态链接库 
    如果直接编译hello.c肯定会报错,因为这里没有main函数,那么我们该怎么处理呢 
    1 都编译成.o文件,然后链接,生成可执行文件 
    Linux下GCC编译过程及静态链接库和动态链接库

    2 利用静态链接库 
    在linux下,库文件一般放在/usr/lib和/lib下, 
    静态库的名字一般为libxxxx.a,其中xxxx是该lib的名称 
    动态库的名字一般为libxxxx.so.major.minor,xxxx是该lib的名称,major是主版本号, minor是副版本号 
    静态库的后缀是.a,它的产生分两步 
    由源文件编译生成一堆.o,每个.o里都包含这个编译单元的符号表 
    ar命令将很多.o转换成.a,成为静态库 
    ar rcs libmyhello.a hello.o 
    Linux下GCC编译过程及静态链接库和动态链接库 
    注意,gcc会在静态库名前加上前缀lib,然后追加扩展名.a得到的静态库文件名来查找静态库文件,因此,我们在写需要连接的库时,只写名字就可以,如libmyhello.a的库,只写:-lmyhello 
    Linux下GCC编译过程及静态链接库和动态链接库 
    gcc -o hello main.c -static -L. -lmyhello 
    -static代表使用静态链接库,-L.代表静态链接库搜索路径 .代表当前路径

    3 动态链接库 
    gcc -shared -fPIC -c hello.c 
    gcc -shared -fPIC -o libmyhello.so hello.o

    -share代表是动态链接库 
    -fPIC命令行标记告诉GCC产生的代码不要包含对函数和变量具体内存位置的引用,这是因为现在还无法知道使用该消息代码的应用程序会将它连接到哪一段内存地址空间。这样编译出的hello.o可以被用于建立共享链接库 
    最后gcc -o hello main.c -L. -lmyhello生成hello可执行文件,注意执行的时候可能会报错,说找不到这个 
    libmyhello.so文件,如果放在/lib或者/usr/lib下,那么默认就能找到,如果放在其他目录下,需要编辑/etc/ld.so.conf文件,加入库文件所在目录的路径,然后 
    运行ldconfig 目录名字,该命令会重建/etc/ld.so.cache文件即可。

    好了,Linux下gcc编译过程,静态链接库和动态链接库就总结到这里,如有问题,欢迎指正,谢谢。

    展开全文
  • Linux系统下使用gcc 5.3编译器编译的boost1.68版本的动态库和静态,多线程参数编译,经测试可用
  • g++编译动态链接库编译简单的动态链接库代码与文件格式编译与调用1、生成动态链接库2、编译调用生成的动态库3、添加环境变量路径4、运行编译依赖第三方库(opencv)的动态链接库代码与文件格式编译与调用 编译简单的...

    编译简单的动态链接库

    代码与文件格式

    在文件夹R003下存在文件
    –R003
    ----R003.h
    ----R003.cpp
    ----main.cpp

    1、头文件:R003.h

    #ifndef R003_H_
    #define R003_H_
    extern "C"
    int IF_Security_DLL(const char* ConfigInform, const char* ConfigPath, char*& ConfigCode);
    void Free_ConfigCode_IF_R009(char **rec_result_pureC);
    #endif 
    

    2、源文件:R003.cpp

    #include "R003.h"
    #include <string.h>
    #include <stdlib.h>
    #include <iostream>
    
    int IF_Security_DLL(const char* ConfigInform, const char* ConfigPath, char*& ConfigCode)
    {
    	std::string Inform = ConfigInform;
    	std::string Path = ConfigPath;
    	std::string Code = "";
    	std::cout << Path.substr(Path.length() - 4, 4) << std::endl;
    	std::cout << Inform.substr(Inform.length() - 5, 5) << std::endl;
    	if (Path.substr(Path.length() - 4, 4) == "Path"&&Inform.substr(Inform.length() - 5, 5) == "IFSSC")
    	{
    		Code = Code + Inform + Path;
    	}
    	else
    	{
    		return 1;
    	}
    	int len = Code.length();
    	std::cout << len << std::endl;
    	char * codeout = (char *)malloc((len + 1) * sizeof(char));
    	//rec_result_pureC_tmp = (char *)malloc(sizeof(char)*len+1);
    	memset(codeout, 0, len + 1);
    	Code.copy(codeout, len);
    	ConfigCode = codeout;
    	return 0;
    }
    
    void Free_ConfigCode_IF_R009(char **rec_result_pureC)
    {
    	if (*rec_result_pureC != NULL)
    	{
    		free(*rec_result_pureC);
    		*rec_result_pureC = NULL;
    	}
    	return;
    }
    

    3、调用测试文件:main.cpp

    #define  _CRT_SECURE_NO_WARNINGS
    
    #include "R003.h"
    #include <string.h>
    #include <iostream>
    
    int main()
    {
    	const char* ConfigInform = "yiqundoushishabi_IFSSC";
    	const char* ConfigPath = "yiqundoushishabi_Path";
    	char* ConfigCode;
    
    	int flag = IF_Security_DLL(ConfigInform, ConfigPath, ConfigCode);
    	
    	std::cout << strlen(ConfigCode) << std::endl;
    	for (int i = 0; i < strlen(ConfigCode); i++)
    	{
    		std::cout << ConfigCode[i];
    	}
    	Free_ConfigCode_IF_R009(&ConfigCode);
    	return 0;
    }
    

    编译与调用

    1、生成动态链接库

    g++ -Wall -g -fPIC -c R003.cpp -o R003.o
    
    g++ -shared R003.o -o libR003.so
    

    上面两条可以合并

    g++ -Wall -g -fPIC -c R003.cpp -shared -o libR003.so
    

    2、编译调用生成的动态库

    g++ -o main main.cpp -L. -lR003
    

    可以通过指令 ldd main查看main依赖项

    3、添加环境变量路径

    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home1/dc/dcstuff/CplusCompile/R003/
    

    4、运行

     ./main
    

    编译依赖第三方库(opencv)的动态链接库

    代码与文件格式

    在文件夹R003opencv下存在文件
    –R003
    ----R003.h
    ----R003.cpp
    ----main.cpp
    ----0.jpg

    1、头文件:R003.h

    #ifndef R003_H_
    #define R003_H_
    
    #include <opencv2/opencv.hpp>
    extern "C"
    int IF_Security_DLL(const char* ConfigInform, const char* ConfigPath, char*& ConfigCode);
    void Free_ConfigCode_IF_R009(char **rec_result_pureC);
    void getimage(cv::Mat image);
    #endif
    

    2、源文件:R003.cpp

    #include "R003.h"
    #include <string.h>
    #include <stdlib.h>
    #include <iostream>
    #include <opencv2/opencv.hpp>
    
    int IF_Security_DLL(const char* ConfigInform, const char* ConfigPath, char*& ConfigCode)
    {
    	std::string Inform = ConfigInform;
    	std::string Path = ConfigPath;
    	std::string Code = "";
    	std::cout << Path.substr(Path.length() - 4, 4) << std::endl;
    	std::cout << Inform.substr(Inform.length() - 5, 5) << std::endl;
    	if (Path.substr(Path.length() - 4, 4) == "Path"&&Inform.substr(Inform.length() - 5, 5) == "IFSSC")
    	{
    		Code = Code + Inform + Path;
    	}
    	else
    	{
    		return 1;
    	}
    	int len = Code.length();
    	std::cout << len << std::endl;
    	char * codeout = (char *)malloc((len + 1) * sizeof(char));
    	//rec_result_pureC_tmp = (char *)malloc(sizeof(char)*len+1);
    	memset(codeout, 0, len + 1);
    	Code.copy(codeout, len);
    	ConfigCode = codeout;
    	return 0;
    }
    
    void Free_ConfigCode_IF_R009(char **rec_result_pureC)
    {
    	if (*rec_result_pureC != NULL)
    	{
    		free(*rec_result_pureC);
    		*rec_result_pureC = NULL;
    	}
    	return;
    }
    
    void getimage(cv::Mat image)
    {
      cv::imwrite("1.jpg",image);
    }
    

    3、调用测试文件:main.cpp

    #define  _CRT_SECURE_NO_WARNINGS
    
    #include "R003.h"
    #include <string.h>
    #include <iostream>
    
    
    int main()
    {
    	const char* ConfigInform = "yiqundoushishabi_IFSSC";
    	const char* ConfigPath = "yiqundoushishabi_Path";
    	char* ConfigCode;
    
    	int flag = IF_Security_DLL(ConfigInform, ConfigPath, ConfigCode);
    	
    	std::cout << strlen(ConfigCode) << std::endl;
    	for (int i = 0; i < strlen(ConfigCode); i++)
    	{
    		std::cout << ConfigCode[i];
    	}
    	Free_ConfigCode_IF_R009(&ConfigCode);
      cv::Mat image = cv::imread("0.jpg");
      getimage(image);
    	return 0;
    }
    

    编译与调用

    1、添加OpenCV的 pkg_config到个人环境变量,一般在安装路径下,比如/usr/local/lib/x86_64-linux-gnu/pkgconfig/
    在.barshrc中添加:

    export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/x86_64-linux-gnu/pkgconfig
    

    添加完成后记得

    source ~/.barshrc
    

    2、编译生成动态库

    g++ -Wall -g -fPIC -c R003.cpp $(pkg-config --cflags --libs opencv)  -shared -o libR003.so
    

    3、编译调用生成的动态库

    g++ -o main main.cpp $(pkg-config --cflags --libs opencv) -L. -lR003
    

    3、添加环境变量路径(可以通过ldd main 查看main的依赖项,如果不能找到刚才生成的libR003 .so,则将当前.so所在的文件夹添加到环境变量中)

    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home1/dc/dcstuff/CplusCompile/R003/
    

    添加完成后记得

    source ~/.barshrc
    

    4、运行
    ./main

    展开全文
  • 1.安装编译环境 yum -y install gcc yum -y install gcc-c++ ...2.编译C动态库 准备三个文件:hello.h 、 hello.c 、 main.c //hello.h #ifndef _HELLO_H_ #define _HELLO_H_ void hello(); #en...

    1.安装编译环境

    yum -y install gcc  
    yum -y install gcc-c++  
    
    yum install -y java-1.8.0-openjdk*
    

    2.编译C动态库

    准备三个文件:hello.h 、 hello.c 、 main.c

    //hello.h
    #ifndef _HELLO_H_
    #define _HELLO_H_
    
    void hello();
    
    #endif	/* _HELLO_H_ */
    
    
    //hello.c
    #include <stdio.h>
    #include "hello.h"
     
    void  hello()
    {
        printf("这是动态链接库接口方法\n");
    }
    
    
    //main.c
    #include <stdio.h>
    #include "hello.h"
     
    int main(void)
    {
    	hello();
    	return 0;
    }
    

    2.1 编译生成so

    gcc hello.c  -fPIC -shared -o libnative.so
    
    参数说明:
        -fPIC 位置无关码
        -shared 按照共享库的方式来链接
    

    2.2 可执行程序链接so

    gcc main.c -L. -lnative -o main
    
    参数说明:
        -L参数:指明要链接的so库所在路径(如-L. 表示当前路径, -L../so 表示当前路径的上一层目录的so子文件夹中)
        -l参数:指明要连接的库的名字,如-lnative 表示要链接libnative.so库
    

    2.3运行可执行程序

    ./main
    

    注意:运行的时候会提示找不到链接库,需要配置系统链接库的位置

    配置系统环境变量:

    //当前窗口有效
    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/root/native  
    
    //永久生效
    vim /etc/profile
    export LD_LIBRARY_PATH=/root/native
    source /etc/profile
    

    3.SpringBoot调用Jni动态库

    • 准备源码文件:HelloJNI.java、HelloNative.h、HelloNative.c
    //HelloJNI.java
    public class HelloJNI {
        //链接库的方法
        public native static void setNum(int num);  
        public native static int get();
    }
    
    //HelloNative.h
    #include <jni.h>
    #ifndef _Included_HelloJNI
    #define _Included_HelloJNI
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    JNIEXPORT void JNICALL Java_com_start_printer_HelloJNI_setNum
      (JNIEnv *, jclass, jint);
    
    JNIEXPORT jint JNICALL Java_com_start_printer_HelloJNI_get
      (JNIEnv *, jclass);
    
    #ifdef __cplusplus
    }
    #endif
    #endif
    
    
    //HelloNative.c
    #include "HelloNative.h"
    int result=888; 
    
    JNIEXPORT void JNICALL Java_com_start_printer_HelloJNI_setNum(JNIEnv * env, jclass jc, jint num)
    {
        result+=num;
    }
    
    JNIEXPORT jint JNICALL Java_com_start_printer_HelloJNI_get(JNIEnv * env, jclass jc)
    {
        return result;
    }
    
    
    • 配置jdk环境变量:
    vim /etc/profile
    JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.181-3.b13.el7_5.x86_64
    PATH=$PATH:$JAVA_HOME/bin  
    CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar  
    export JAVA_HOME  CLASSPATH  PATH
    

    3.1 编译生成jni的so库

     gcc HelloNative.c -fPIC -I $JAVA_HOME/include -I $JAVA_HOME/include/linux -shared -o libHelloNative.so 
    

    3.2 集成到springboot工程

    • 拷贝HelloJNI.java文件到jni接口声明的包中
    • 拷贝so文件到resouces/native文件夹下
    • 动态加载so类:
    public class NativeLoader {
        /**
         * 加载项目下的native文件,DLL或SO
         *
         * @param dirPath 需要扫描的文件路径,项目下的相对路径
         * @throws IOException
         * @throws ClassNotFoundException
         */
        public synchronized static void loader(String dirPath) throws IOException, ClassNotFoundException {
            Enumeration<URL> dir = Thread.currentThread().getContextClassLoader().getResources(dirPath);
            // 获取操作系统类型
            String systemType = System.getProperty("os.name");
            //String systemArch = System.getProperty("os.arch");
            // 获取动态链接库后缀名
            String ext = (systemType.toLowerCase().indexOf("win") != -1) ? ".dll" : ".so";
            while (dir.hasMoreElements()) {
                URL url = dir.nextElement();
                String protocol = url.getProtocol();
                if ("jar".equals(protocol)) {
                    JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
                    JarFile jarFile = jarURLConnection.getJarFile();
                    // 遍历Jar包
                    Enumeration<JarEntry> entries = jarFile.entries();
                    while (entries.hasMoreElements()) {
                        JarEntry jarEntry = entries.nextElement();
                        String entityName = jarEntry.getName();
                        if (jarEntry.isDirectory() || !entityName.startsWith(dirPath)) {
                            continue;
                        }
                        if (entityName.endsWith(ext)) {
                            loadJarNative(jarEntry);
                        }
                    }
                } else if ("file".equals(protocol)) {
                    File file = new File(url.getPath());
                    loadFileNative(file, ext);
                }
    
            }
        }
    
        private static void loadFileNative(File file, String ext) {
            if (null == file) {
                return;
            }
            if (file.isDirectory()) {
                File[] files = file.listFiles();
                if (null != files) {
                    for (File f : files) {
                        loadFileNative(f, ext);
                    }
                }
            }
            if (file.canRead() && file.getName().endsWith(ext)) {
                try {
                    System.load(file.getPath());
                    System.out.println("加载native文件 :" + file + "成功!!");
                } catch (UnsatisfiedLinkError e) {
                    System.out.println("加载native文件 :" + file + "失败!!请确认操作系统是X86还是X64!!!");
                }
            }
        }
    
        /**
         * @throws IOException
         * @throws ClassNotFoundException
         * @Title: scanJ
         * @Description 扫描Jar包下所有class
         */
        /**
         * 创建动态链接库缓存文件,然后加载资源文件
         *
         * @param jarEntry
         * @throws IOException
         * @throws ClassNotFoundException
         */
        private static void loadJarNative(JarEntry jarEntry) throws IOException, ClassNotFoundException {
    
            File path = new File(".");
            //将所有动态链接库dll/so文件都放在一个临时文件夹下,然后进行加载
            //这是应为项目为可执行jar文件的时候不能很方便的扫描里面文件
            //此目录放置在与项目同目录下的natives文件夹下
            String rootOutputPath = path.getAbsoluteFile().getParent() + File.separator;
            String entityName = jarEntry.getName();
            String fileName = entityName.substring(entityName.lastIndexOf("/") + 1);
            System.out.println(entityName);
            System.out.println(fileName);
            File tempFile = new File(rootOutputPath + File.separator + entityName);
            // 如果缓存文件路径不存在,则创建路径
            if (!tempFile.getParentFile().exists()) {
                tempFile.getParentFile().mkdirs();
            }
            // 如果缓存文件存在,则删除
            if (tempFile.exists()) {
                tempFile.delete();
            }
            InputStream in = null;
            BufferedInputStream reader = null;
            FileOutputStream writer = null;
            try {
                //读取文件形成输入流
                in = NativeLoader.class.getResourceAsStream(entityName);
                if (in == null) {
                    in = NativeLoader.class.getResourceAsStream("/" + entityName);
                    if (null == in) {
                        return;
                    }
                }
                NativeLoader.class.getResource(fileName);
                reader = new BufferedInputStream(in);
                writer = new FileOutputStream(tempFile);
                byte[] buffer = new byte[1024];
    
                while (reader.read(buffer) > 0) {
                    writer.write(buffer);
                    buffer = new byte[1024];
                }
    
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (in != null) {
                    in.close();
                }
                if (writer != null) {
                    writer.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                System.out.println("path :" + tempFile.getPath());
                System.load(tempFile.getPath());
                System.out.println("加载native文件 :" + tempFile + "成功!!");
            } catch (UnsatisfiedLinkError e) {
                System.out.println("加载native文件 :" + tempFile + "失败!!请确认操作系统是X86还是X64!!!");
            }
        }
    }
    
    • SpringBoot工程启动类新增初始化加载so的Bean(实现工程启动只加载一次so库)
    @Bean
    public void loadLib() {
        //根据操作系统判断,如果是linux系统则加载c++方法库
        String systemType = System.getProperty("os.name");
        String ext = (systemType.toLowerCase().indexOf("win") != -1) ? ".dll" : ".so";
        if (ext.equals(".so")) {
            try {
                NativeLoader.loader("native");
            } catch (Exception e) {
                System.out.println("加载so库失败");
            }
        }
        System.out.println("loaded");
    }
    
    • 加载完成即可调用HelloJNI.java声明的native方法

    3.3 注意事项

    android studio下编译的jni库,在linux下springboot加载不成功。必须在linux重新编译一次动态库才能加载成功。

    源码工程
    我的博客

    展开全文
  • Linux编译boost动态链接库和静态链接库   1. 先去Boost官网下载需要的Boost版本, 我下载的是boost_1_55_0版本, 然后解压文件。   2. 使用cd命令进入解压后目录: cd boost_1_55_0, 执行下面的命令:  $./...
  • lua动态链接库编译 c++调用lua的的方法 linux中调用lua的环境配置
  • Linux中C++编译、使用动态链接库

    千次阅读 2018-02-07 15:44:58
    Linux中so为共享动态链接库。下面我们通过一个四则运算的实例来学习动态链接库。 首先是头文件:my_math.h: /** * my_math.h */ // a + b int Add(int a, int b); // a - b int Minus(int a, int b); // a ...
  • Linux qtcreator动态加载动态链接库案例
  • 如果程序需要使用某个动态链接库中的函数,则,在程序的编译阶段和之后的运行阶段都需要这个动态链接库, 即 编译时链接和运行时链接 1. 编译时链接  这个过程是由ld(链接器)来执行的。ld查找动态库中是否含有...
  • Lua:Linux 平台编译 Lua 为动态链接库

    千次阅读 2018-07-22 16:13:56
    在 Lua 源码的 makefile 中,没有编译动态链接库的目标(tagete),只可编译为静态库。 如何将 Lua 编译为动态链接库呢? 仔细研究下 Lua 的 makefile 文件,其实很简单。 Lua 版本:lua-5.3.5 我的 Lua 代码...
  • linux动态库编译的依赖问题

    千次阅读 2019-03-08 09:16:48
    这里主要是想试验一下,对一个具有多层嵌套的动态库进行编译时,是否要把最底层的也包含进来的问题,结论是:只要直接依赖的名称,不需要最底层名称。 一,目录结构 ZZZ ├── add │ ├── add.cpp │ └...
  • g++ 编译动态链接库

    2019-08-26 14:41:33
    g++ 编译动态链接库linux中动态链接库的后缀为(.so),windows中的后缀为(.dll)mac 中为(.dylib) g++ -shared -fPIC -o ecd.so add.c -share指为共享的,-fPIC表示position independent code位置无关,这是动态...
  • Linux动态库编译及使用示例

    千次阅读 2019-08-07 16:50:21
    1、动态库编译 下面通过一个例子来介绍如何生成一个动态库。这里有一个头文件:so_test.h,三个.c文件:test_a.c、 test_b.c、test_c.c,我们将这几个文件编译成一个动态库:libtest.so。 //so_test.h: #...
  • linux下g++编译与使用静态动态库
  • 有在Linux开发程序的经验的朋友都应该知道,在64位Linux编译动态链接库时,一般在编译时要加上参数-fPIC或者-mcmodel=large,不然在链接时会报错。但是却很少有人真正理解这些参数对于动态链接库的意义,所以今天...
  • 通过java实现SCTP通信时,需要编译SCTP的动态链接库 本资源描述了如何在linux上进行.so文件的编译过程
  • Linux下生成动态链接库

    千次阅读 2018-04-18 17:32:53
    【摘要】动态链接库是在编译器编译之后生成 obj 文件之后,将几个链接文件和动态链接库中的文件链接起来,在链接器中将几个目标文件组合在一起然后生成可执行文件 exe 文件,而生成动态链接库的这一步骤是由编译器...
  • Linux下gcc编译生成动态链接库*.so文件并调用它 gcc -c test.c将生成test.o的目标文件 gcc -o app test.c将生成可执行程序app 动态库*.so在linux下用c和c++编程时经常会碰到,最近在网站找了几篇文章介绍动态库的...
  • 此文件为交叉编译动态链接库。使用时放到开发板/usr/local 目录下
  • linux 下“cannot find -l*”错误解决方法。
  • 根据GenDll.cpp文件,分别生成动态库.so和静态....使用ar命令生成.a文件,可参考:Linux动态库(.so)和静态(.a) # 1、准备工作,编译方式、目标文件名、依赖路径的定义。 CC = g++ CFLAGS := -Wall -O3 -s...
  • Linux编译动态库及使用

    万次阅读 2017-12-20 18:14:43
    说明: linux下生成和使用动态库的步骤如下: ...4,把libxxx.so放入链接库的标准路径,或指定 LD_LIBRARY_PATH,才能运行链接了libxxx.so的程序。     一, 生成动态库 1)test.c文件 #...
  • arm-Linux 编译动态库 简单实例

    千次阅读 2014-07-31 14:25:20
    本文讲述了一个简单的例子 ,很好的解释了“编译动态库”。  一、准备工作  1.使用oracle VM Virtualbox软件安装Ubuntu虚拟机  2.下载好相关的软件并传输到虚拟机下,安装好交叉编译器。  二、编译...
  • C++ 在 Linux编译动态链接库

    千次阅读 2011-04-22 12:13:00
    $g++ -fPIC -o test.o -c test.c $g++ -shared -o test.so test.o   外部头文件需要添加-I参数 $g++ -Ipath -fPIC -o test.o -c test.c c++编写的切勿用gcc来编译,否则在外部程序...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 97,255
精华内容 38,902
关键字:

linux编译动态链接库

linux 订阅