- 易迪拓培训,专注于微波、射频、天线设计工程师的培养
Labwindows 虚拟仪器高级应用:十六进制文本文件转换
1.2 十六进制文本文件转换
1.2.1 十六进制文本文件转换设计方法
在LabWindows/CVI 程序设计中,一些参数需要进行初始化,如字符串常量、动态链接库、静态链接库等。如字符串常量内容非常大,通常都会以文本文件的形式存储到磁盘上,动态链接库、静态链接库等也是如此。有没有办法,将这些文件都一同打包到可执行文件中,使其只包含一个可执行文件呢?将常量文本、各种库文件都打包到可执行文件中,便于文件的管理与操作。办法是有的,可以将这些文件导出为十六进制文本文件格式,并以C 语言的.h 头文件形式出现,在.c 源程序中通过#include 方式引用并在实现代码中调用,这些文件就可以通过隐式方式随可执行文件一起装载到内存中,调用简单而且方便。
在本例程中,由于涉及大量数据的转换,而这些转换又是在一个for 循环语句中完成的,因此,程序执行期间不能及时响应外部的操作,如拖拽标题栏、点击面板按钮等,为了提高系统响应的及时性以及算法执行效率,采用多线程技术,将转换算法放入一个新线程中执行,即实现界面逻辑与算法逻辑的分离,效果会更好一些。
一个采用了多线程技术的应用程序可以更好地利用系统资源。其主要优势在于充分利用了CPU 的空闲时间片,可以用尽可能少的时间来对用户的要求做出响应,使得进程的整体运行效率得到较大提高,同时增强了应用程序的灵活性。更为重要的是,由于同一进程的所有线程是共享同一内存的,所以不需要特殊的数据传送机制,不需要建立共享存储区或共享文件,从而使得不同任务之间的协调操作与运行、数据的交互、资源的分配等问题更加易于解决。
对于本例程来说,界面逻辑虽然在算法执行过程中可以实现移动、按钮点击等操作,但如果在转换没有完成时进行第二次转换操作(如点击转换按钮),可能会出现逻辑错误,因此,最好在程序设计时考虑按钮的有效性或按钮自锁功能。
1.2.2 十六进制文本文件转换程序设计
(1)面板设计
编写一个十六进制文本文件转换程序,可将各种文件如.txt、.dll、.lib、.obj 、.exe 等转换为十六进制文本格式,如“0x0A3, 0xB4, … ”等,并以.h 或.c 等格式存储,方便在程序运行时载入。点击转换按钮,弹出打开文件对话框,选择要转换的文件,之后会弹出保存对话框,提示保存为何种类型的文件,最后程序自动进行转换,在转换进度条中显示实际的转换进度,进度条到达满刻度时,转换完成。在编辑状态下双击Numeric Slide 控件,弹出Edit Numeric Slide 对话框,设置Data type 为int,Control mode 为Indicator ,点击Range Values… 按钮,弹出Edit Range Values 对话框,设置最小值Minimum 为0,如图1-5 所示,点击Show/Hide Parts… 按钮,弹出Show/Hide Parts 对话框,设置相关属性为No Markers 、No Ticks 等,如图1-6 所示。面板设计如图1-7 所示,面板中主
图1-5 Edit Range Values 对话框要
图1-6 Show/Hide Parts 对话框
图1-7 十六进制文本文件转换面板
表1-5 控件属性设置表
常量名 |
控件类型 |
控件的主要属性 |
PANEL |
Panel |
标题:十六进制文本文件转换回调函数:panelCB |
PROGRESS |
Numeric Slide |
标题:转换进度 |
TRANSLATE |
Command Button |
标题:转换回调函数:Translate |
(2)程序源代码
//头文件声明
#include
#include
#include
#include
#include
#include "十六进制文本文件转换.h"
//全局静态变量
static int BytesRead;
static CmtThreadFunctionID ThreadID;
static int panelHandle;
static char *buffer;
char SaveDir[MAX_PATHNAME_LEN];
//线程回调函数声明
int CVICALLBACK HextoText (void *functionData);
//主函数
int main (int argc, char *argv[])
{
if (InitCVIRTE (0, argv, 0) == 0)
return -1;
/* out of memory */
if ((panelHandle = LoadPanel (0, " 十六进制文本文件转换.uir", PANEL)) < 0)
return -1;
DisplayPanel (panelHandle);
RunUserInterface ();
//释放资源
free (buffer);
DiscardPanel (panelHandle);
return 0;
}
//面板回调函数
int CVICALLBACK panelCB (int panel, int event, void *callbackData,
int eventData1, int eventData2)
{
switch (event)
{
case EVENT_CLOSE:
QuitUserInterface (0);
break;
}
return 0;
}
//转换按钮
int CVICALLBACK Translate (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
int SaveSel;
int Present;
ssize_t FileSize;
int sel;
char path[MAX_PATHNAME_LEN];
int FileHandle;
switch (event)
{
case EVENT_COMMIT:
// 打开文件,获得文件信息
sel = FileSelectPopup ("", "*.txt", "*.txt;*.dll;*.lib;*.obj;*.exe", " 打开", VAL_LOAD_BUTTON,
0, 0, 1, 1, path);
Present = GetFileInfo (path, &FileSize);
// 保存为十六进制文本文件
SaveSel = FileSelectPopup ("", "*.h", "*.h;*.c;*.txt", " 保存", VAL_SAVE_BUTTON, 0, 0, 1, 1,
SaveDir);
// 判断文件是否存在
if ((sel > 0) && (Present == 1) && (SaveSel > 0))
{
buffer = malloc (FileSize * sizeof(char) + 1);buffer[0] =
'