目录
概括
市面很多提供大数据的服务器同时提供了API接口,而这些接口绝大多数都使用了C/C++编写的动态库(.dll/.so),这些源动态库有的提供了export C接口可以供其他语言调用(如Python,当前很多程序员更喜欢用Python来写一些服务器后台脚本),有的没有提供export C 接口,即便提供了export C 接口也可能需要二次封装才能满足自身需求,这就可能涉及到API二次嵌套依赖来重新封装自己的c++接口。这里以linux为例讲解踩坑过程
原生动态库.so
其实这个动态库是大数据输出方提供给我们的动态库,这里我们就临时制作一个了,顺便看多个源码作者的动态库.so
1.cpp源码
[add.cpp ]
int add(int a, int b)
{
return a+b;
}
[add_p.cpp ]
int add_p(int a, int b)
{
printf( a+b);
}
2.头文件.h
[add.h]
extern "C" {int add(int a, int b);} // 暴露多个函数可以直接使用{ },如果就一个函数可以不用
[add_p.h]
extern "C" {int add_p(int a, int b);}
3.多个.cpp制作 .so
g++ -o libadd.so add.cpp add_p.cpp -shared -fPIC
g++ 参数:
.o : 后面跟目标文件 (Object file)
-shared :制作动态库
-fPIC : 表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通
过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。
封装自己的动态库
因为上面的源动态库(假设上制作的动态库是数据方提供的,所以我们只有最后封装的libadd.so文件和两个头文件add.h,add_p.h,没有源码文件),源动态库只是提供了基础功能,我们需要完善增加一些我们需要的功能后,在封装成我们需要的动态库。
1.调用动态库
a.cpp源码
[test.cpp]
#include <iostream>
#include <string.h>
#include "add.h"
#include "add_p.h"
using namespace std;
int p()
{
int a =10;
int b = 20;
add(a,b);
add_p(a,b);
return 0;
}
b. 头文件.h
[test.h]
extern "C" { int p(); }
c.二次封装嵌套动态库
因为在test.cpp中调用了前面的原生动态库,所有这次封装应该注意:
g++ -o libtest.so test.cpp -L./ -ladd -shared -fPIC
g++ 参数:
-L:指定动态库所在的路径,例如:-L / lib 或者 -L ./
-l:(小写L),跟在-L的路径后面,指定动态库的文件名,需要注意的是,去掉lib和.so,比如:源动态库文件名为:libadd.so,那么这里就写“ -L ./ -ladd”
找不到源动态库的坑
按照上面的完成后在linux下输入 ldd :libtest.so 会列举出引用的动态库,但是libadd.so一行会提示找不到这个文件。
处理方案有三个:
1.将库路径增加到环境变量 LD_LIBRARY_PATH 中(不推荐)
进入libadd.so动态库的目录下
export LD_LIBRARY_PATH = .:$LD_LIBRARY_PATH
之所以不推荐,是因为这种方式一旦窗口关闭下次重启的时候还要重复操作。
2.配置 /etc/ld.so.conf 文件,增加 ./**/lib/ 路径,执行 ldconfig -v(推荐)
进入系统目录etc,输入:
sudo vi ld.so.conf
打开 ld.so.conf后 按i键进入编辑状态,把前面源动态的目录输入(例如: /home/root/mypro/lib),注意目录写到最后一层文件夹即可,按ESC退出,再按Ctrl + :后输入wq(保存并退出),退出后在命令行输入 sudo ldconfig -v, 完成!
这是推荐的方式,但是这种方式也有个坑,笔者在腾讯云的linux服务器上出现了bug,提示找不到输入的目录,很奇怪,不知道是不是输入的路径有错误,如果使用这种方式的朋友在遇到这种类似情况可酌情考虑下面的第三中方法。
3.把动态库复制到系统目录的lib下(酌情考虑)
sudo cp libadd.so /lib
这个方式简单粗暴,但是要酌情考虑,除非是上面第二种方案出现bug久久不能解决,而我们开发的这个服务器只有很少的几个动态库,确保他们不会重名!!!
使用这个方法,在制作二次封装动态库的时候 -L后面的路径要修改,让其指向系统的lib,例如:
g++ -o libtest.so test.cpp -L/lib -ladd -shared -fPIC