利用objcopy把资源文件编译进动态库或可执行文件
玦尘
2018-09-01 14:26:52
1597
收藏
3
4 篇文章
0 订阅
7 篇文章
0 订阅
工作中收到一个需求,需要把caffe的prototxt文件和模型文件编译进动态库,以后链接了这个动态库的工程,不需要依赖其他资源文件,只需要执行相关函数就可以直接进行人脸跟踪。以前提供的库是库,模型是模型,一旦不同版本的模型和库文件配对出了错误,整个跟踪结果就会出现一些乱七八糟的错误,现在打包成一个即可彻底避免这种情况。
首先需要明确,资源文件只不过是一堆存储在磁盘上的二进制串,按照一定规则读入内存后,便会起到我们期望的作用。那如果事先把资源文件作为全局变量直接编入可执行文件或者动态库中,在程序执行过程中,再按照一定规则解读这段内存,当然也可以达到同样的效果。
这便需要用到objcopy和nm命令来实现。objcopy和nm都是Linux系统提供的命令,简单来说,objcopy可以把资源文件转换成.o文件,这样才能编译到可执行文件或者库文件中,而nm命令则用来解读.o文件的符号表,定位具体的数据地址。具体操作如下:
模型文件为A.caffemodel。首先完成准备工作:先利用caffe提供的接口ReadNetParamsFromTextFileOrDie将A.caffemodel读取到内存中的,以caffe::NetParameter的结构存在,再通过WriteProtoToBinaryFile函数将其写入磁盘,成为B.binarymodel文件,得到了B.binarymodel文件,则准备工作完成,只要反序列化B文件,就能在内存中重建caffe::NetParameter结构。
接下来解决如何把B.binarymodel文件编入可执行文件的问题。首先用如下命令得到.o文件,-I为输入文件格式,-O为为输出文件格式,-B为输出的架构,这里采用的是二进制文件输出为x86 64位架构下的.o文件
objcopy -I binary -O elf64-x86-64 -B i386 B.binarymodel C.o
然后使用nm命令得到符号地址
nm C.o
结果如下:
100000000000000df D _B_caffe_binarymodel_end200000000000000df A _B_caffe_binarymodel_size30000000000000000 D _B_caffe_binarymodel_start
可以看到,原来的B.binarymodel被转化为一个char数组存储在C.o文件中,其中_B_caffe_binarymodel_start代表起始地址,_B_caffe_binarymodel_end为结束地址,_B_caffe_binarymodel_size为数组长度
在最终交付的库文件代码中,可以通过如下方式来调用C.o文件中的信息,直接贴代码吧:
1extern char _B_binarymodel_start[];2extern int _B_binarymodel_size;3 4caffe::NetParameter modelParam; 5long modelLen = (long)&_B_binarymodel_size;6std::string modelData(_B_binarymodel_start, modelLen); 7modelParam.ParseFromString(modelData);8net->CopyTrainedLayersFrom(modelParam);
把caffe网络结构文件也编入可执行文件的方法类似,略去不表,贴一下最后调用的代码:
1 extern char _vgg16_caffe_binaryproto_start[];2 extern int _vgg16_caffe_binaryproto_size;3 4 caffe::NetParameter netParam;5 long netLen = (long)&_vgg16_caffe_binaryproto_size;6 std::string netData(_vgg16_caffe_binaryproto_start, netLen);7 netParam.ParseFromString(netData);8 netParam.mutable_state()->set_phase(TEST);9 netParam.mutable_state()->set_level(0);10 net.reset(new Net<float>(netParam))
免登录复制
有时候_B_binarymodel_size这个值获取可能会失败,比如代码跑在ARM平台上的时候,这时候可以使用_B_caffe_binarymodel_end – _B_caffe_binarymodel_start来获取长度
由于这个方法是把文件作为全局变量的形式存储在动态库中,应此文件大小受到全局变量最大大小限制。在32位操作系统上,全局变量区最大为4GB,故这种方法最多只能用于不大于4GB的资源文件
显示推荐内容
请登录后查看评论内容