一、关于so文件?
1、ELF格式文件、共享库、动态库,类似Windows下的DLL,了解这些就差不多了;
2、test.h和test1.c、test2.c、test3.c,用这几个文件编译成一个共享库:libtest.so;当然,我们进行调用时也可以生成.o或者.a文件,这些和windows下面基本一致,就不再赘述。
$ gcc test1.c test2.c test3.c -fPIC -shared -o libtest.so
3、调用libtest.so共享库
$ gcc test.c -L libtest.so_path -ltest -o test
二、回到libdarknet.so
1.makefile
代码如下:
GPU=1 # 1启用GPU,0启用CPU
CUDNN=1 # GPU加速
CUDNN_HALF=1 # 为Tensor Core构建加速检测3倍,训练2倍
OPENCV=1 # 允许使用OpenCV,后面重点注意
AVX=0
OPENMP=0 # CPU加速
LIBSO=1 # 生成libdarknet.so共享库
ZED_CAMERA=0
ZED_CAMERA_v2_8=0
这里面注意几个地方:NVCC=nvcc这里一定要换成自己的CUDA路径,一般做好软连接后统一都是/usr/local/cuda/bin,需要不同的CUDA版本,删除、更新软连接即可,此处配置不用改变。
2.yolo_v2_class.hpp
该头文件最重要的是对detect()方法的定义,这里有三个,尤其我们经常习惯使用OpenCV做图像处理时,我们想调用第三个 std::vector<bbox_t> detect(cv::Mat mat, float thresh = 0.2, bool use_mean = false),但是却经常出现以下错误:no matching function for call to "Detector::detect(cv::Mat&, double, bool)",no known conversion for argument 1 from "cv::Mat" to "std::__cxx11::string *****",就是说不能强制转换类型Mat到image_t。
LIB_API std::vector<bbox_t> detect(std::string image_filename, float thresh = 0.2, bool use_mean = false);
LIB_API std::vector<bbox_t> detect(image_t img, float thresh = 0.2, bool use_mean = false);
std::vector<bbox_t> detect(cv::Mat mat, float thresh = 0.2, bool use_mean = false)
其实这一切就是#ifdef OPENCV和#endif在作怪,也怪一时大意没注意,因为在makefile中编写编译规则的时候已经赋值OPENCV=1,所以能够正常调用detect接口,并且能够正常画框显示。
那么我们如果做第三方调用时,就需要重新# define OPENCV并且时在调用该头文件之前,或者也可以将该yolo_v2_class.hpp中#ifdef OPENCV和#endif注释掉,直接就启用该函数,就能解决以上出现的一个低级问题。
3.关于第三方so共享库调用
编译程序经常遇到“ld:cannot find -lXXX方法”的错误,就是链接器找不到XXX库,可以先使用以下命令查找系统中是否存在该库,以libdarknet.so为例:
$ ld -ldarknet --verbose
此时将会出现系列信息,可以查看到libdarknet.so是否存在,如果不存在则需要安装和生成,如果存在,而ld命令又未找到,这时应该考虑共享库路径问题了。
一般在Linux系统中,共享库调用的顺序是:(1)编译目标代码时指定的动态库搜索路径(-L 共享库path)(2)环境变量LD_LIBRARY_PATH指定的动态库搜索路径(3)配置文件/etc/ld.so.conf中指定的动态库搜索路径(4)默认的动态库搜索路径/lib(5)默认的动态库搜索路径/usr/lib
LIBRARY_PATH环境变量:指定程序静态链接库文件搜索路径
LD_LIBRARY_PATH环境变量:指定程序动态链接库文件搜索路径
三.软连接建立和删除
软连接(ln)为某一个文件在另外一个位置建立一个不同的链接,这样操作之后就不需要在每一个需要的目录下都放一个必须相同的文件,我们只要在某个固定的目录,放上该文件,然后在其它的 目录下用ln命令链接它就可以,不必重复的占用磁盘空间。
ln参数是-s–symbolic:表示符号。使用-s参数它只会在你选定的位置上生成一个文件的镜像,不会占用磁盘空间;不使用-s参数, 它会在你选定的位置上生成一个和源文件大小相同的文件,无论是软链接还是硬链接,文件都保持同步变化。
(1)建立软连接
ln -s 源目录 软连接地址
例如:ln -s /usr/local/cuda-10.2 /usr/local/cuda
(2)删除软连接
rm -rf 软链接地址
(3)修改软连接
ln -snf 新源目录 软链接地址
总结
差不多就这些了把,熟能生巧,好记性不如烂笔头。