2018-08-16 19:49:38 qq_41985711 阅读数 458
  • 宏定义与预处理、函数和函数-C语言专题第6部分

    本课程综合讲解了C语言的预处理和宏定义,详细讲述了宏定义的细节规则和头文件包含等常用预处理;然后讲述了函数的使用、函数库的使用,静态链接库和动态链接库等的制作和使用。本章的目标是提升大家对函数及函数库的认知,提升在实战中使用函数库解决问题的能力。

    8172 人正在学习 去看看 朱有鹏

有一文件 apple.c 需要做成在 arm 平台下可以使用动态库,且该文件依赖与 jpeg 图片解码库 libjpeg.so
gcc 编译器中 -I 代表头文件路径 -L 代表依赖的库所在路径
1: 生成 apple.o 文件
编译命令: arm-none-linux-gnueabi-gcc apple.c -o apple.o -I /home/gec/jpeg/include -c fPIC -ljpeg
/home/gec/jpeg/include: 为 jpeg 库需要的头文件路径
ljpeg: 指明需要链接的库名为: libjpeg

2; 生成 libapple.so 文件
编译命令: arm-none-linux-gnueabi-gcc -shared -fPIC -o libapple.so apple.o
libapple.so: 生成的库名,库名要以 “lib” 为前缀,".so" 为后缀

3: 现在我有一个叫 user.c 的文件要包含 libapple.so 这个库
编译命令: arm-none-linux-gnueabi-gcc user.c -o userelf -ldl -L/home/gec/jpeg/lib/ -ljpeg
userelf: 生成的可执行文件名
/home/gec/jpeg/lib/ -ljpeg: 我的 user.c 与jpeg库没有直接联系的为什么要链接呢?
原因: user.c 需要链接 libapple.solibapple.so 要依赖与 libjpeg.so。如果在编译 user.c 时没有
链接 libjpeg.so 库,那么在 userelf 运行时,libapple.so 就无法找到 libjpeg.so 。这种情况在编译
时时不会有任何提示信息的,需要自己注意。
ldl: 在程序中打开库的话需要链接库相关操作的动态库
库操作相关函数
dlopen函数: void *dlopen(const char *filename, int flags)

//使用方法:
void *handle = dlopen("libapple.so", RTLD_NOW);
if (handle == NULL)
{
	perror("打开库出现的错误或者库不存在");
	exit(1);
}
//假如在 libapple.so 中有一个 char *show(int a); 函数
char *(*show)(int a) = dlsym(handle, "show");
//现在在 user.c 中的函数指针 show 就是libapple.so 中的 show 函数,二者没有区别

失败或者错误时返回值为空 :NULL
filename: 可以是绝对路径下的文件名, 也可以是单独的文件名。后者需要设置环境变量 LD_LIBRARY_PATH
flags : 指明什么时候加载动态库,一般立即加载。则 flags 可以是: RTLD_NOW

dlsym函数: void *dlsym(void *handle, const char *symbol)
返回值为函数指针,通过该函数指针可以直接使用到libapple.so 中的 symbol 函数
handle: 由 dlopen 得到的动态库指针
symbol: 需要使用的函数的函数名

最后还是写一下静态库的制作
1,制作*.o文件:
gcc example.c -o example.o -c -fPIC
2,制作静态库:
ar rcs libxxx.a *.o

注意:
当同一个目录下,有重名的动态、静态库,默认情况下会自动连接动态库
如果要指定静态库:
gcc example.c -o exmaple -L dir/ -lname -static
库名:除了前缀后缀之外的,比如libxxx.so ,库名就是xxx

2016-08-12 10:14:42 lihuajie1003 阅读数 823
  • 宏定义与预处理、函数和函数-C语言专题第6部分

    本课程综合讲解了C语言的预处理和宏定义,详细讲述了宏定义的细节规则和头文件包含等常用预处理;然后讲述了函数的使用、函数库的使用,静态链接库和动态链接库等的制作和使用。本章的目标是提升大家对函数及函数库的认知,提升在实战中使用函数库解决问题的能力。

    8172 人正在学习 去看看 朱有鹏

linux下动态链接库的制作:

so可以供多个进程使用,不同进程调用同一个so文件,

so文件源程序不需要main函数,有也不会被执行。

下面通过一个简单例子,来学习.so文件的制作跟使用。

/* 
 * max.h 
 * 
 */  
  
/*条件编译*/  
#ifndef MAX_H_  
#define MAX_H_  
  
#ifdef __cpluscplus  
extern "C"{  
#endif  
   int max(int a,int b);  
#endif /* MAX_H_ */  

/* 
 * max.cpp
 * 
*/
#include "max.h"
int max(int a,int b)  
{  
    return a>b?a:b;  
}  

链接库的制作:

编译c程序:
gcc -shared -fpic XXX.c -o XXX.so

编译c++程序:
g++ -shared -fpic XXX.cpp -o XXX.so

/* 
 * main.cpp 
 * 
 */  
#include <stdio.h>  
#include "max.h"  
int main(void)  
{  
    printf("call max function results is: %d\n",max(20,12));  
    return 0;  
}  
/* 使用libmax.so库 
 * gcc -o  main main.c -L. -lmax 
 * 
 *-L.: 在当前路径下寻找.so文件 
 *-lmax: 要链接这个libmax.so文件 
 * 
 * */  

编译main.cpp

       g++ -o main main.cpp -lmax

此时需要注意的是应该把libmax.so 放到/usr/lib目录中否则会出现错误

error while loading shared libraries: libmax.so: cannot open shared object file: No such file or directory

      ./main 结果出现20说明动态链接库制作正确。

如果要是在QT中调用,需要加上头文件和.so文件的绝对路径

INCLUDEPATH + =" "
LIBS += ""


$ g++ hello.cpp  -fPIC -shared -o libhello.so

$ g++ main.cpp -L. -lhello -o main

交叉编译步骤一致:

(1)  $arm-linux-g++ hello.cpp -fPIC -shared -o libarmhello.so

(2)  $arm-linux-g++ main.cpp -L. -larmhello -o armhello

交叉编译的时候出现错误:fatal error:opencv2/imgproc/imgproc.hpp:no such file or directory

解决方法:把交叉编译好的opencv下的include中的opencv2拷贝到交叉编译器中的include下

我的交叉编译好的opencv和opencv2路径是在:/opt/arm/include  

/opt/arm/include  文件下的opencv2 复制到/opt/fsl-linaro-toolchain/arm-fsl-linux-gnueabi/include即可。


2017-01-01 20:59:28 crazy_koala 阅读数 3600
  • 宏定义与预处理、函数和函数-C语言专题第6部分

    本课程综合讲解了C语言的预处理和宏定义,详细讲述了宏定义的细节规则和头文件包含等常用预处理;然后讲述了函数的使用、函数库的使用,静态链接库和动态链接库等的制作和使用。本章的目标是提升大家对函数及函数库的认知,提升在实战中使用函数库解决问题的能力。

    8172 人正在学习 去看看 朱有鹏
制作一个动态库
我们可以使用gcc工具来制作一个动态库
示例:自己制作一个动态库,库函数的功能是传递一个字符串并输出。
第一步:需要准备3个文件:hello.h、hello.c、test.c。其中hello.h和hello.c用于制作动态库,test.c是测试程序主函数

第二步:使用gcc编译生成动态库
gcc hello.c -fPIC -c -o hello.o
gcc hello.o -shared -o libmyhello.so
(或者直接一步:gcc hello.c -fPIC -shared -o libmyhello.so)
gcc参数解析:
⒈-fPIC(或-fpic):表示编译为位置独立的代码。位置独立的代码即位置无关代码,在可执行程序加载的时候可以存放在内存内的任何位置。若不使用该选项则编译后的代码是位置相关的代码,在可执行程序加载时是通过代码拷贝的方式来满足不同的进程的需要,没有实现真正意义上的位置共享。
⒉-shared:指定生成动态链接库

ldd hello
linux-gate.so.1 => (0xb77b0000)
libmyhello.so => not found
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb75f6000)
/lib/ld-linux.so.2 (0xb77b1000)
第三步:定位自己制作的动态库
为了让系统能成功找到自己制作的动态库,需要定位到该动态库的位置。有三种方式:
⑴把自己制作的库拷贝到/usr/lib和/lib下。
⑵在LD_LIBRARY_PATH环境变量中添加自己制作的库所在的位置。/
⑶添加/etc/ld.so.conf.d/XXX.conf文件(XXX需要自己命名),把库所在的路径添加到文件末尾并执行ldconfig刷新。 //对所用用户有效


第一种:将库拷贝到/usr/lib和/lib下。
sudo cp libmyhello.so /usr/lib
sudo cp libmyhello.so /lib
此时再执行./hello即可得到正确的显示结果。

第二种:修改LD_LIBRARY_PATH环境变量:
sudo vim /etc/bash.bashrc 对所有用户生效 或者修改 ~/.bashrc 这样就只对当前用户生效

在文件最后,添加:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/linux/file/dongtaiku
保存退出,重启终端,此时再执行./hello即可得到正确的显示结果。。

第三种:添加/etc/ld.so.conf.d/XXX.conf文件
sudo vim /etc/ld.so.conf.d/my.conf
在文件内添加动态库的目录
/home/linux/file/dongtaiku
保存退出,执行ldconfig使设置生效
sudo ldconfig

第四步:修改编译时的搜索库路径
方法一:可以直接在gcc编译时 -L加库路径
方法二:添加库路径至LIBRARY_PATH环境变量

第五步:
创建动态库的同时那以避免我们会使用到头文件
我们应该修改头文件的路径的环境变量C_LIBRARY_PATH
2014-04-14 11:04:12 kankan231 阅读数 500
  • 宏定义与预处理、函数和函数-C语言专题第6部分

    本课程综合讲解了C语言的预处理和宏定义,详细讲述了宏定义的细节规则和头文件包含等常用预处理;然后讲述了函数的使用、函数库的使用,静态链接库和动态链接库等的制作和使用。本章的目标是提升大家对函数及函数库的认知,提升在实战中使用函数库解决问题的能力。

    8172 人正在学习 去看看 朱有鹏

原文:http://yanghe9012.blog.163.com/blog/static/21398220320137982452330/

假设在math目录下已编辑好add.c sub.c div.c mul.c func_point.c文件,func_point.c为包含main()的源文件!

   动态库的制作:

   方法一:

  1. gcc -c -fPIC add.c sub.c div.c mul.c  //-c表示生成.o目标文件,-f后加一些编译选项,PIC表示与位置无关  
  2. gcc -shared -o libmymath.so add.o sub.o mul.o div.o//创建共享库mymath,添加add.o,sub.o,mul.o,div.o目标文件  
  3. sudo mv libmymath.so /usr/lib  
  4. gcc func_point.c -lmymath//-l后面加动态链接库名字  

     方法二:

  1. gcc -c -fPIC add.c sub.c div.c mul.c  //-c:生成.o目标文件,-f后加一些编译选项,PIC表示与位置无关  
  2. gcc -shared -o libmymath.so add.o sub.o mul.o div.o//创建共享库mymath,添加add.o,sub.o mul.o div.o目标文件  
  3. export  LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.//注意此操作后把当前目录加入环境变量中  
  4. gcc func_point.c  -L. -lmymath//-l后面加动态链接库名字  

    方法三:

  1. gcc -c -fPIC add.c sub.c div.c mul.c  //-c:生成.o目标文件,-f后加一些编译选项,PIC表示与位置无关  
  2. gcc -shared -o libmymath.so add.o sub.o mul.o div.o//创建共享库mymath,添加add.o,sub.o mul.o div.o目标文件  
  3. sudo vi /etc/ld.so.conf//把你的动态库路径加入此文件中  
  4. sudo ldconfig  
  5. gcc func_point.c  -L. -lmymath//-l后面加动态链接库名字  
    ldd   显示可执行程序所需的共享库。
   定义好框架,不断增加动态库!!

  静态库制作:

  1. ar -crs libmymath.a add.o sub.o div.o mul.o/*创建静态库mymath,添加add.o,sub.o,mul.o,div.o,-c:创建归档文件 -r:插入 -s:若归档文件中包含了对象模式,可利用此参数建立备存文件的符号表  ar -crs libmymath.a *.o */  
  2. gcc func_point.c -L. -lmymath//-L在哪个目录下找库 -l找哪个库,-lm可以链接到标准算数库,-lpthread可以连接到Linux标准线程库  
  3. ar -d libmymath.a add.o//删除一个  
  4. ar -r libmymath.a add.o//增加一个  

    静态库在程序链接时用到,链接器把程序所需的代码从静态库中拷贝到可执行程序中,可执行程序会增大;动态库在程序加载时用到,程序在加载时,会先检查需要哪些动态库连接,然后从内存中找到这些动态库的地址,最后加载动态库运行程序。


2019-09-25 08:16:40 qq_41286360 阅读数 23
  • 宏定义与预处理、函数和函数-C语言专题第6部分

    本课程综合讲解了C语言的预处理和宏定义,详细讲述了宏定义的细节规则和头文件包含等常用预处理;然后讲述了函数的使用、函数库的使用,静态链接库和动态链接库等的制作和使用。本章的目标是提升大家对函数及函数库的认知,提升在实战中使用函数库解决问题的能力。

    8172 人正在学习 去看看 朱有鹏

1 制作第三方动态库的方法

  1. 使用gcc得到.o,得到和位置无关的代码。
gcc sub.c add.c div.c mult.c -c -fpic
  • -fpic/-fPIC: 使用相对地址记录代码的位置
  1. 使用gcc得到动态库
gcc -shared add.o sub.o div.o mult.o -o libcalc.so

或者:

gcc -shared -o libcalc.so add.o sub.o div.o mult.o


在这里插入图片描述

2 动态库的使用

gcc main.c -o app -I ./include/ -L ./ -lcalc
  • 这是只是保证在连接的时候没问题

在执行的时候如何定位共享文件的呢?

  • 当系统加载可执行代码时候,能够知道其所依赖的库的名字,但是还需要知道绝对路径。此时就需要系统的动态载入器(dynamic linker/loader)来获取该绝对路径。
  • 对于elf格式的可执行程序,是由ld-linux.so来完成的,它先后搜索elf文件的 DT_RPATH段 —> 环境变量LD_LIBRARY_PATH —> /etc/ld.so.cache文件列表 —> /lib/,/usr/lib目录找到库文件后将其载入内存。

3 决加载动态库失败的问题

解决动态库找不到的问题:

第一种: 将动态库的绝对路径添加到 LD_LIBRARY_PATH 中

  1. 测试时候使用的, 终端关闭, 设置失效:
    在当前终端中执行: export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/itcast/library
  2. 长久设置, 将export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/itcast/写到配置文件中
    • 用户级别: ~/.bashrc
      添加: export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/itcast/library
    • 系统级别: /etc/profile
      添加: export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/itcast/library
      添加完成执行命令, 使修改生效:
      . ~/.bashrc -> . 相当于 source
      . /etc/profile
      source /etc/profile

第二种: 在 /etc/ld.so.cache 添加动态库路径

需要间接完成这个操作:
1. 找一个文件: /etc/ld.so.conf
2. 执行一个命令, 进行更新: sudo ldconfig

Linux制作动态库

阅读数 361

没有更多推荐了,返回首页