探索cmd调编译器的方式实现数组转二进制文件
2016-06-09 16:35
211 查看
本文主要介绍一个综合运用各种编程工具“将数组转换为二进制文件”的探索案例。事实上,通过纯C/C++编程的方式,也能解决这个问题,但是,本文想强调的是,在实际工作中,需要发散思维和探索精神,能够想出一些新鲜的idea,权当一个coder的自娱自乐。
一、需求介绍
某日,DSP工程师提出一个需求:应用程序(上位机)根据用户的选择,通过驱动实时加载对应版本的DSP程序到DSP芯片(下位机)。DSP工程师提供的DSP程序是由CCS(一个IDE工具)生成的“*.h”文件,该文件包含一些注释和一个数组,如下(截取部分):
注:该数组就是DSP程序,需要转换成二进制码,load到DSP芯片中。真实的code数组比这个大的多,达几十k。
DSP工程师会生成几个这样的.h文件,对应不同版本的DSP程序。应用层需要根据用户的选择,读不通的.h文件,来获取数组的内容,并转换成二进制码,再传送给DSP芯片。
最原始的办法就是写一个C/C++程序模块来读.h文件,丢弃不相干的字符,截取数组的内容,并将“0x80”类型的字符串转换为uint8_t型的数。
要实现这么一个功能,并保证可靠性,还是需要写不少代码的,而且需要测试多个.h文件样本,比较耗时。当时,项目比较紧急,我灵机一动,想到了下面这么一个几行代码就可实现的方案。
二、巧用编译器
事实上,这个.h文件保存的数组形式,就是我们日常在代码中写的数组形式。平常我们根本不用去关心它,直接交给编译器,编译器会去读取文件并将它解析为字节,以二进制形式保存在内存中。这么说来,实际上我要做的是编译器的活。那么,为什么不能直接交给编译器去做呢?
基于此,我根本没必要去写这么一个功能模块,直接交给编译器去做。而且,编译器还带错误检查功能,比人工实现的功能更稳定可靠。我最先给出的方案如下:
1,使用VS新建一个win32工程,在main.cpp中添加如下几行代码:
注:上述代码就是将.h文件中的数字bootCode以二进制形式输出为一个“bootCode.bin”文件。
2,对于DSP工程师提供的各个.h文件,都进行一次如上的编译和运行,产生一个.bin文件,并重命名为不同的名字。如:1.bin、2.bin、3.bin。。。
3,将上面生成的各个.bin文件放到应用软件的工程目录下,只需要在应用软件添加如下几行代码即可读入二进制文件:
注:以上三步即可实现将数组转为二进制码。
这个方案还有意想不到的好处:
1)应用程序读.bin文件(二进制文件)比都.h文件(文本文件)快,且在运行时不需要再进行解析,效率要高不少。
2)保存相同的信息,.bin文件(二进制文件)比都.h文件(文本文件)小很多。
3)更换或新增DSP程序,只需要重新生成.bin文件,不需要再编译应用程序的代码。
4)用户一般不会去操作.bin文件,可以防止文件损坏。
三、提升用户体验
就这样,我在非常短的时间内解决了这么一个需求。但是,在使用一段时间后发现,每次生成一个.bin文件,需要修改文件名和启动VS来编译和运行,经过5个步骤,而且DSP工程不习惯用VS,他们希望能够做出要给exe,点击直接生成。
要到一步生成,传统的办法当然是自己用C/C++实现编译器的活,又绕回去了。我当然不甘心,想想有没有其他办法?
办法当然是有的,还是在原有的基础上改进,如果能将上面的几步操作打包,进行批处理,不就解决这个问题了么?批处理,对,就是用命令行方式编译C++程序。
思路有了,于是开始试验windows下用命令行编译C++程序。我参考了几篇博客:点击打开链接,在命令行下面调VC++编译器,但是Windows OS和VS的版本不同,环境变量的设置各不相同,折腾了一个小时,也没成功。时间紧迫,急中生智,我想到了我的机器上安装了Qt5.3,之前也用命令行编译过Qt程序。而且,我们的应用程序界面是用Qt开发的,在实验室的每台机器上都安装了Qt,可以很方便用Qt来实现这个功能。
四、升级方案
1,配置Qt的环境变量
1)到Qt的安装目录下,去搜索“.bat”文件,可以搜到一个“qtevn2.bat”文件。不同的qt版本,该文件的名字可能不同,有的是“qtvar.bar”,基本上都是“环境-environment”和“变量-variable”两个单词的缩写。
2)打开该bat文件,安装它的path设置环境变量,如下:
我的机器就是要在系统环境变量的“path"栏增加两项:
C:\Qt\Qt5.4.1\5.4\mingw491_32\bin; 这个是qmake.exe所在的路径
C:\Qt\Qt5.4.1\Tools\mingw491_32\bin; 这个是mingw32-make所在的路径
3)打开环境变量设置窗口,添加环境变量QTDIR:
变量名:QTDIR
变量值:C:\Qt\Qt5.4.1\5.4\mingw491_32
注:设置了这一项,就可以在cmd窗口使用qmake命令,否则报”该命令不识别“。
4)打开环境变量设置窗口,添加环境变量QMAKESPEC:
变量名:QMAKESPEC
变量值:C:\Qt\Qt5.4.1\5.4\mingw491_32\mkspecs\win32-g++
参考博客:点击打开链接
2,新建一个文件夹”Array2Binary“,放入三个文件:
”main.cpp" "pcieBootCode_6657.h" "translate.bat“
3,编写translate.bat文件
@echo off
echo current path : %~dp0
%~d0
cd %~dp0
del/s/q pcieBootCode_6657.h
ren *.h pcieBootCode_6657.h
qmake -project
qmake
mingw32-make clean
mingw32-make
cd release
Array2Binary.exe
copy bootCode.bin ..\
pause
注:”mingw32-make clean“是为了清除以前生成的东西,也可以使用如下方法:
4,将需要转换的.h文件放到该文件夹下,注意不要和"pcieBootCode_6657.h"重名。
5,双击.bat文件,即可在该文件夹下生成一个”bootCode.bin“文件。
一、需求介绍
某日,DSP工程师提出一个需求:应用程序(上位机)根据用户的选择,通过驱动实时加载对应版本的DSP程序到DSP芯片(下位机)。DSP工程师提供的DSP程序是由CCS(一个IDE工具)生成的“*.h”文件,该文件包含一些注释和一个数组,如下(截取部分):
/ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ //typedef unsigned char uint8_t; uint8_t bootCode[] = { 0x80, 0x00, 0xF6, 0xE0, 0x00, 0x00, 0xFE, 0x60, 0x80, 0x00, 0x00, 0x00, 0x02, 0x04, 0x03, 0xE2, 0x92, 0x46, 0x0C, 0x6E, 0x00, 0x8C, 0xA3, 0x62, 0x02, 0x28, 0x03, 0xE2, 0x92, 0x46, 0x0C, 0x6E, 0x00, 0x8C, 0xA3, 0x62, 0x02, 0x44, 0x03, 0xE2, 0xE2, 0x40, 0x00, 0x00, 0x92, 0x46, 0x0C, 0x6E]
注:该数组就是DSP程序,需要转换成二进制码,load到DSP芯片中。真实的code数组比这个大的多,达几十k。
DSP工程师会生成几个这样的.h文件,对应不同版本的DSP程序。应用层需要根据用户的选择,读不通的.h文件,来获取数组的内容,并转换成二进制码,再传送给DSP芯片。
最原始的办法就是写一个C/C++程序模块来读.h文件,丢弃不相干的字符,截取数组的内容,并将“0x80”类型的字符串转换为uint8_t型的数。
要实现这么一个功能,并保证可靠性,还是需要写不少代码的,而且需要测试多个.h文件样本,比较耗时。当时,项目比较紧急,我灵机一动,想到了下面这么一个几行代码就可实现的方案。
二、巧用编译器
事实上,这个.h文件保存的数组形式,就是我们日常在代码中写的数组形式。平常我们根本不用去关心它,直接交给编译器,编译器会去读取文件并将它解析为字节,以二进制形式保存在内存中。这么说来,实际上我要做的是编译器的活。那么,为什么不能直接交给编译器去做呢?
基于此,我根本没必要去写这么一个功能模块,直接交给编译器去做。而且,编译器还带错误检查功能,比人工实现的功能更稳定可靠。我最先给出的方案如下:
1,使用VS新建一个win32工程,在main.cpp中添加如下几行代码:
#include <fstream> #include <stdint.h> // for unit8_t #include "pcieBootCode_6657.h" // dsp codes int main() { std::ofstream out("bootCode.bin", std::ios::out | std::ios::binary | std::ios::trunc); out.write((char*)bootCode, sizeof(bootCode)); // bootCode is a unit8_t array out.close(); return 0; }
注:上述代码就是将.h文件中的数字bootCode以二进制形式输出为一个“bootCode.bin”文件。
2,对于DSP工程师提供的各个.h文件,都进行一次如上的编译和运行,产生一个.bin文件,并重命名为不同的名字。如:1.bin、2.bin、3.bin。。。
3,将上面生成的各个.bin文件放到应用软件的工程目录下,只需要在应用软件添加如下几行代码即可读入二进制文件:
char * buffer; long size; std::ifstream in(filename, std::ios::in | std::ios::binary | std::ios::ate); // filename is the name of .bin size = in.tellg(); in.seekg(0, std::ios::beg); buffer = new char[size]; in.read(buffer, size); in.close(); ... // do something delete[] buffer;
注:以上三步即可实现将数组转为二进制码。
这个方案还有意想不到的好处:
1)应用程序读.bin文件(二进制文件)比都.h文件(文本文件)快,且在运行时不需要再进行解析,效率要高不少。
2)保存相同的信息,.bin文件(二进制文件)比都.h文件(文本文件)小很多。
3)更换或新增DSP程序,只需要重新生成.bin文件,不需要再编译应用程序的代码。
4)用户一般不会去操作.bin文件,可以防止文件损坏。
三、提升用户体验
就这样,我在非常短的时间内解决了这么一个需求。但是,在使用一段时间后发现,每次生成一个.bin文件,需要修改文件名和启动VS来编译和运行,经过5个步骤,而且DSP工程不习惯用VS,他们希望能够做出要给exe,点击直接生成。
要到一步生成,传统的办法当然是自己用C/C++实现编译器的活,又绕回去了。我当然不甘心,想想有没有其他办法?
办法当然是有的,还是在原有的基础上改进,如果能将上面的几步操作打包,进行批处理,不就解决这个问题了么?批处理,对,就是用命令行方式编译C++程序。
思路有了,于是开始试验windows下用命令行编译C++程序。我参考了几篇博客:点击打开链接,在命令行下面调VC++编译器,但是Windows OS和VS的版本不同,环境变量的设置各不相同,折腾了一个小时,也没成功。时间紧迫,急中生智,我想到了我的机器上安装了Qt5.3,之前也用命令行编译过Qt程序。而且,我们的应用程序界面是用Qt开发的,在实验室的每台机器上都安装了Qt,可以很方便用Qt来实现这个功能。
四、升级方案
1,配置Qt的环境变量
1)到Qt的安装目录下,去搜索“.bat”文件,可以搜到一个“qtevn2.bat”文件。不同的qt版本,该文件的名字可能不同,有的是“qtvar.bar”,基本上都是“环境-environment”和“变量-variable”两个单词的缩写。
2)打开该bat文件,安装它的path设置环境变量,如下:
echo off echo Setting up environment for Qt usage... set PATH=C:\Qt\Qt5.4.1\5.4\mingw491_32\bin;C:\Qt\Qt5.4.1\Tools\mingw491_32\bin;%PATH% cd /D C:\Qt\Qt5.4.1\5.4\mingw491_32
我的机器就是要在系统环境变量的“path"栏增加两项:
C:\Qt\Qt5.4.1\5.4\mingw491_32\bin; 这个是qmake.exe所在的路径
C:\Qt\Qt5.4.1\Tools\mingw491_32\bin; 这个是mingw32-make所在的路径
3)打开环境变量设置窗口,添加环境变量QTDIR:
变量名:QTDIR
变量值:C:\Qt\Qt5.4.1\5.4\mingw491_32
注:设置了这一项,就可以在cmd窗口使用qmake命令,否则报”该命令不识别“。
4)打开环境变量设置窗口,添加环境变量QMAKESPEC:
变量名:QMAKESPEC
变量值:C:\Qt\Qt5.4.1\5.4\mingw491_32\mkspecs\win32-g++
参考博客:点击打开链接
2,新建一个文件夹”Array2Binary“,放入三个文件:
”main.cpp" "pcieBootCode_6657.h" "translate.bat“
3,编写translate.bat文件
@echo off
echo current path : %~dp0
%~d0
cd %~dp0
del/s/q pcieBootCode_6657.h
ren *.h pcieBootCode_6657.h
qmake -project
qmake
mingw32-make clean
mingw32-make
cd release
Array2Binary.exe
copy bootCode.bin ..\
pause
注:”mingw32-make clean“是为了清除以前生成的东西,也可以使用如下方法:
rd/s/q release mkdir release
4,将需要转换的.h文件放到该文件夹下,注意不要和"pcieBootCode_6657.h"重名。
5,双击.bat文件,即可在该文件夹下生成一个”bootCode.bin“文件。
相关文章推荐
- what's my passwd of mysql? on mysql5.7
- Codeforces-Round-#356-(Div.-2)-Bear-and-Five-Cards
- MyEclipse 10 启动配置优化
- gem5模拟器使用介绍(一)
- synchronized关键字小结(一)
- bootstrap学习总结-js组件(四)
- SQLAlchemy使用说明之ORM
- Java并发编程之——CyclicBarrier的使用
- win10 uefi Ubuntu14.04双系统
- matlab练习程序(粒子群优化PSO)
- 77.PS接收来自PL的按键中断
- ORA-01034: ORACLE not available
- 关于c的printf和scanf的知识点----菜鸟笔记(1)
- mysql5.7,utf-8字符编码问题
- 04_登陆注册
- 如何使用hugo搭建个人博客(三):添加follow与修改share的方式
- 边框
- MyBatis常用的jdbcType类型
- ros_arduino_bridge功能包集的使用错误及解决方法总结
- URAL 1099 一般图带花树匹配