概述
易语言支持库升级之后,要保证向下兼容性,主要是做到以下几点:
一:保证原有的易语言源程序(.e)能正常打开(兼容点1)、正常编译(兼容点2)、编译结果正确(兼容点3);
二:保证原有的易语言程序(.exe)能正常运行(兼容点4)、运行结果正确(兼容点5)。
这里说的“原有的易语言源程序”和“原有的易语言程序”是指,替换新版支持库文件之前,使用旧版支持库编写的易语言源程序,和使用该源程序编译生成的可执行程序。
本文主要就此问题结合具体情况进行分析和总结。
一,为支持库增加一条命令
新增加的命令,必须放在所有原有命令的后面,否则将违反兼容点2和4,更无法保证兼容点3和5。这是因为,在源程序和EXE中,记录的都是命令的索引,一旦在中间插入一条命令,将导致后面的命令索引全变了,进而导致非常严重的错位问题。只要记住,总是在所有命令的最后添加新的命令,就不会引入兼容性问题。具体到数据类型的成员方法,与上面的分种一致,因为它也是使用支持库中唯一的全局函数表的,但这里引入了一个新的细节,有一个LIB_DATA_TYPE_INFO.m_pnCmdsIndex 用于指定方法在全局函数表中的命令索引,所以通过它可以调整各成员方法的顺序,这种做法通常不会引入兼容性问题。
二,为命令增加一个参数,或修改命令的参数
新增加的参数,必须放在所有参数的后面,否则将违反兼容点2,3,4,5;必须允许省略该参数(AS_DEFAULT_VALUE_IS_EMPTY)或该参数有默认值(AS_HAS_DEFAULT_VALUE);同时在编写代码读取该参数值时要小心,须判断nArgCount和MDATA_INF.m_dtDataType(否则违反兼容点4,5),大致大代如下:
void fn_Global_SetWindowRgn (PMDATA_INF pRetData, INT nArgCount, PMDATA_INF pArgInf) { int nArg1 = pArgInf[0].m_int; int nArg2 = pArgInf[1].m_int; //假设第三个参数是新版添加的参数 int nArg3 = 0; if(nArgCount > 2 && pArgInf[2].m_dtDataType != _SDT_NULL) { nArg3 = pArgInf[2].m_int; } //... }
修改一个已有命令的参数时,不能随便修改数据类型,否则将违反兼容点2,3,4,5,要改也只能改成通用型(同时在代码中根据参数传递来的真实类型(MDATA_INF.m_dtDataType)做相应处理)。参数的名称和说明,因为都是文本,可以随便改,有会有兼容性问题,但不要改的意思与原来相反哦(排除原来失误写反了的情况),改变参数语义往往会导致代码改动,进而导致违反兼容点5。
三,为窗口组件增加属性
新增加的属性,必须放在已有属性的后面,否则违反兼容点4,5,因为易语言运行时是通过属性的索引读写属性值的。然后在序列化属性值时,提高一个版本号,读取时先判断版本,旧版序列化出的数据少,就不能多读。在此提示,序列化属性值时,一定要先写出版本号,如果没有版本号,后续的兼容性问题多多。
(TODO:这一段另成一文)但即使有了版本号,使用不当,也会导致升级时的麻烦,我前一段就遇到过,代码有这么一句:if(dwVersion > CURRENT_VER) return FALSE; 版本号比现在能处理的版本号大,出现在什么情况呢,用旧版支持库打开/运行用新版支持库编译的易源程序/程序。返回假是合理的(毕竟不能完全处理这种情况),但是比较粗暴(这意味着无法用旧版支持库打开用新版支持库编写的源程序/程序,这不是向下兼容的问题,是向上兼容的问题),如果能尽量读取,放弃不能识别的数据,温和的处理,效果更好。简单的把这条判断语句删除,有用吗?当然没用,旧版的支持库已经在用户手上了,编译结果是确定的,你的改动只能体现在新版中,而对旧版无能为力。解决这个问题需要技巧,我采取的方案是,版本号不升反降!即,把CURRENT_VER减小,那么我序列化出的数据,版本号比以前还小,旧版支持库里的那条判断(if(dwVersion > CURRENT_VER))就不起作用了,嘿嘿。新的序列化数据版本更低,但写的数据更多,需要担心旧版支持库读出多余的数据来吗?当然不用,旧版支持库的编译结果和运行结果是确定的。只要新版支持库中识别出这种情况,不要因为版本号小就认为是旧版就行了,同时后续升级的方便,再引入一个新的版本号,存到原有序列化数据的最后,这样再次升级时直接判断新版本号就行了,原有的那套版本号停止使用。这一段有点乱,需整理。
四,为数据类型增加私有成员
如果某个数据类型已经有了一个或多个私有成员,升级时需要增加一个私有成员,该怎么办,直接在LIB_DATA_TYPE_ELEMENT 数组中添加一项吗?不行!这样将违反兼容点4,5,因为对象所占用内存是在由EXE分配的,旧的EXE中只为对象分配了N个成员的空间,而新库要去访问第N+1个成员,不就发生内存访问越界的错误了吗?解决方案是,把原来的N个私有成员连用新增加的成员,集中存储到一块新分配的内存中,然后把这个内存地址存储到原有的第一个私有成员位置上(原有的其它成员位置废弃不用)。因为即使是旧EXE也会调用新支持库中的构造函数和析构函数,所以改变私有成员存储位置不会影响程序的执行。这种方案对代码的影响是非常大的,需要修改很多地方(所有对私有成员的读写),但是为了保证支持库的向下兼容性,这种付出是值得的。
最后
以上就是聪慧外套为你收集整理的总结升级易语言支持库保证向下兼容性的全部内容,希望文章能够帮你解决总结升级易语言支持库保证向下兼容性所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复