关关难过关关过——编译edm

摘自《上海质子治疗装置注入器远程控制系统的构建》

EDM 和 MEDM安装哪个?

EDM 和 MEDM 是当前常见的 OPI 界面开发工具。 OPI 界面开发工具 EDM(Extensible Display Manager)是由美国橡树岭实验室(ORNL)主要承担开发的,通过 OPI 控制界面可以对 IOC 实时数据库里面的数据进行监测与控制。

基于图形用户界面 GUI(Graphical User Interface)的 MEDM(Motif Editor and Display Manager)也是一种图形化的 OPI 界面开发工具。早期在 EPICS 刚刚发展起来的时候,MEDM 广泛被世界各大实验室用来进行控制界面的开发。它的风格和功能和 EDM 大致一样,用其开发的控制系统在运行过程中也较为稳定,但它具有控件类型比较单一,且无法进行扩展的缺点。因现已经暂停了对 MEDM的开发,所有对于那些将要新建的加速器控制系统建议不要再使用 MEDM 进行控制界面的开发。

EDM 的安装,EDM 作为 EPICS 的一个扩展工具,在安装目录上有要求,需要在/usr/local/epics/extension/src 目录下创建目录 edm,然后把EDM的安装包解压到该文件夹下面,在安装之前也需要进行一些环境变量的配置,进入到/usr/local/epics/extensions/configure 目录下修改 RELEASE 文件,修改为EPICS_BASE=/usr/local/epics/base/,保存后退出。在编译之前,可以事先安装一些软件包以为在编译的时候报错进行多次编译,在 CentOS 下安装软件包的命令为 yum install packet,packet 为需要安装的软件包的包名,通常可能需要安装的是:gcc-c++、readline-devel、motif-devel、libXtst-devel 以及giflib-devel。还有需要的一些软件包根据在EDM编译时提示的错误再进行安装。EDM的编译,进入到/usr/local/epics/extension/src/edm 下,在终端运行 make,如无报错,则 EDM编译完成。

编译出现的错误

然后编译中出现错误如下图

然后查了一下,说是

const char*是不能直接赋值到char*的,这样编译都不能通过,理由:假如可以的话,
那么通过char*就可以修改const char指向的内容了,这是不允许的.

所以char*要另外开辟新的空间

怎么解决?

find -name 文件名 找到remFileOpen.cc

打开文件(vim ~/.vimrc,然后set nu 然后保存退出就可以永久显示行号辣,set nonu就是关闭行号)

我看到文件是这样的,

 413 static int fileReadable (
 414   char *fname )//定义了一个字符型指针
 415 {
 416 
 417 FILE *f;
 418 
 419 char nameToCheck[255+1];//最大为256,不知道为啥要+1
 420 
 421 int result, len1, len2, remain;
 422 
 423 char *first, *last;
 424 
 425   // if filename is of the form name[parm].ext,
 426   // use name.ext in the "is readable check".
 427   first = index( (const char *) fname, (int) '[' );
 428   if ( first ) {
 429     last = rindex( (const char *) fname, (int) ']' );
 430   }
      
       // 如果括号里为真,则执行last
       // &位操作,&&逻辑与,条件满足则为真
 431   if ( first && last && ( first < last ) ) {
       // 这句是说,如果first,last存在,且first<last,则执行以下语句
  
 432     len1 = (long) first - (long) fname;//[的地址与fname的地址差
 433     if ( len1 > 255 ) len1 = 255;

        //char *strncpy(char *dest, const char *src, int n),
        //把src所指向的字符串中以src地址开始的前n个字节复制到dest所指的数组中,
        //并返回被复制后的dest。

 434     strncpy( nameToCheck, fname, len1 );//这里len1小于255
 435     nameToCheck[len1] = 0;//这里取fname[前的字符串到nameToCheck,使得第len1-1个为0
 436     remain = 255 - len1;//[之后的字符串的位数
         //strlen所作的仅仅是一个计数器的工作,它从内存的某个位置(可以是字符串开头,中间某个
         //位 置,甚至是某个不确定的内存区域)开始扫描,直到碰到第一个字符串结束符'\0'为止,然
         //后返回计数器值(长度不包含'\0')。
 437     len2 = strlen( fname ) - (long) last + (long) fname - 1;
 438     if ( len2 > remain ) len2 = remain;
 439     strncat( nameToCheck, last+1, len2 );
         //函数原型:extern char *strcat(char *dest,char *src);

         //功能:把src所指字符串添加到dest结尾处(覆盖dest结尾处的'\0')并添加'\0'。
 440     nameToCheck[len1+len2] = 0;
 441   }
        
        //这个if里的作用就是把[]里的内容去掉,剩下的内容拼到一起


 442   else {
 443 
 444     strncpy( nameToCheck, fname, 255 );
 445     nameToCheck[255] = 0;
 446 
 447     // else if filename is of the form name.ext?params,
 448     // use name.ext in the "is readable check".
 449     first = index( (const char *) nameToCheck, (int) '?' );
 450     if ( first ) {
 451       *first = (char) 0;
 452     }
 453 
 454     // else use fname without any changes

根本看不懂这个函数是干啥的,于是开始百度。

首先,index函数和rindex函数

char * index(const char *s, int c);
char * rindex(const char *s, int c);

函数说明:index()用来找出参数s 字符串中第一个出现的参数c 地址,然后将该字符出现的地址返回。字符串结束字符(NULL)也视为字符串一部分。

返回值:如果找到指定的字符则返回该字符所在地址,否则返回0.

函数说明:rindex()用来找出参数s 字符串中最后一个出现的参数c 地址,然后将该字符出现的地址返回。字符串结束字符(NULL)也视为字符串一部分。

返回值:如果找到指定的字符则返回该字符所在的地址,否则返回0。

file *fp

FILE *fp

//FILE是在C标准库中(stdio.h)中定义的一个结构体,通常用指针的方式保存在内存中,其内容描述了一个
//文件,或者说”流“更恰当。
//标准库中提供了通用的函数来读取和写入流,如fopen,fclose等等

//FILE指针的使用在C中很广泛,如一些常用的输入/出流就是FILE*的类型,如

//stdin、stdout、stderr等

//当然,C++中用类进行了封装,更加具体和方便。

//综上,FILE*fp就是声明了一个类型为FILE的,名为fp的指针(fp指file pointer, 文件指针),用于保存
//流信息

所以这里的问题就是,一开始定义的是char *fname,char nametocheck[],后面用的时候如first里

first= index((const char*)fname,(int)‘[’),把const char*的指针传给first,是char*,所以要把const char*转换为char*

怎么转呢?https://blog.csdn.net/hebbely/article/details/79577880

const char*转换为char*


#include "stdafx.h"
#include <iostream>
 
int _tmain(intargc, _TCHAR* argv[])
{
    const char* constc = "Hello World!"; //初始化const char* 类型
    char* c = nullptr;              //初始化char*类型
    c= const_cast<char*>(constc);   //const char*类型转char*类型
    printf_s("%s\n", constc);       //打印const char* 类型数据
    printf_s("%s\n", c);            //打印char*类型数据
    return 0;
}

然后又出现缺gif_lib.h文件的错误

这里的.h文件是什么呢?C语言和C++语言的头文件
我们一般在.h类的头文件里面只放入函数声明,宏定义,函数原型。
而具体的实现在.cpp文件里面
比如你在<math.h>里面看到的数学函数都只有声明
具体实现在<math.cpp>里面
在编译的时候,编译器会自动加载和.h匹配的.CPP文件。

然后下载gif_lib.h文件,http://rpmfind.net/linux/rpm2html/search.php?query=/usr/include/gif_lib.h

用yum localinstall ****安装

安装之后有出现错误,zlibversion 没有声明,是在文件的开头没有调用zlib的头文件,加上#include <zlib.h> #include <zconf.h>就行了

在终端运行 make,如无报错,则 EDM编译完成。EDM 和 EPICS BASE 以及 EPICS Extensions 不一样,安装完之后还需要进行一些必要的配置才能正常使用。在终端上输入

cd  /usr/local/epics/extensions/src/edm/setup,

接着输入

export  HOST_ARCH=linux-x86_64,

再输入 source   setup.sh。配置完上面一步之后,安装先前配置 EPICS BASE 的环境变量一样,打开.bashrc 文件。添加一下内容

EDMOBJECTS=/usr/local/epics/extensions/src/edm/setup

EDMHELPFILES=/usr/local/epics/extensions/src/edm/helpFiles

EDMBASE=/usr/local/epics/extensions/src/edm

EDMPVOBJECTS=/usr/local/epics/extensions/src/edm/setup

EDMFILES=/usr/local/epics/extensions/src/edm/setup

EDMDATAFILES=:~/.

EDMWEBBROWSER=firefox

配置完之后,正常情况下就可以使用 EDM 了

猜你喜欢

转载自blog.csdn.net/weixin_41965702/article/details/82423718