|

本帖最后由 项目部002 于 2022-6-16 16:49 编辑
大家好,为大家带来了使用C语言为易语言编写支持库的教程。
本教程中涵盖了编写一般支持中的语法,说明,注意事项。
--
教程以:易语言官方提供的docs.txt(支持库开发说明文件)以及易语言官方提供的例程(HtmlView)作为参考,为大家来讲解使用C语言来制作易语言支持库。
同时针对一些小的技巧,写法做出了说明,适合想要编写支持库的广大易友。
docs.txt
(143.11 KB, 下载次数: 169)
易语言支持库开发手册2013版.zip
(367.04 KB, 下载次数: 306)
该教程会继续完善,希望大家能够提出宝贵意见及遇到的bug。
感谢您的回复,学习时,请多多参考官方例程,也可以在论坛,或通过搜索引擎查找对应的教程、源码等。
计划:今后会以docs.txt作为基本,制作更加具有说明性,例程更加齐全,更加完善和功能强大的支持库开发文档帮助手册,以图+文+例程的方式,详解支持库开发。
课程大纲:- 易语言支持库第一课
- 什么是易语言支持库?
- 易语言支持库的开发文档。
- 前期准备工作,环境,路径配置。
- lib2.h 必须文件,包含支持库类型、宏定义等
- fnshare.h fnshare.cpp 可选文件,提供了一些常用的代码封装。
- -----------------------
- 入口函数:
- [line:75]
- #define FUNCNAME_GET_LIB_INFO "GetNewInf" // 取本支持库的PLIB_INFO指针的输出函数名称
- typedef PLIB_INFO (WINAPI *PFN_GET_LIB_INFO) (); // GetNewInf的函数原型
- LIB_INFO结构体定义 [line:85] - [line:280]
- 需要注意的位置:m_nMajorVersion,m_nMinorVersion,_LIB_OS,m_pfnNotify
- -----
- 需要了解的数据类型定义及长度:
- [line:282]-[line:420]
- 额外阅读: 3、数据存储方式
- -----
- 支持库环境通知方法*[line:422]
- **新版VS不支持默认参数。
- 同时需要定义:NotifySys [line:444]
- ------
- 以上为支持库信息定义,定以后便可以编译生成并且在易语言中调用支持库。
复制代码
- 易语言支持库第二课
- 向支持库中添加一些“东西”
- 添加常量。
- 添加全局命令。
- 常量的定义:
- LIB_CONST_INFO 定义 [line:468]
- 修改 : LIB_INFO结构体定义
- INT m_nLibConstCount; // 常量数目。 [line:277]
- PLIB_CONST_INFO m_pLibConst; // 指向常量定义数组。 [line:278]
- ---------------
- 实现全局命令
- 要向编写一个全局的命令,将要分成3个步骤:
- 1.定义一个:CMD_INFO [line:539]
- 注意:_CMD_OS
- 2.如果存在参数,则定义参数。ARG_INFO [line:608]
- 将参数信息写入CMD_INFO中。
- m_nArgCount [line:601]
- m_pBeginArgInfo [line:602]
- 3.定义命令函数体。 [line:665]
- typedef void (*PFN_EXECUTE_CMD) (PMDATA_INF pRetData, INT nArgCount, PMDATA_INF pArgInf);
- 例子 [line:766]
复制代码
- 易语言支持库第三课
- 多实现几个命令
- 接上一课作业:
- 将所有参数定义到同一个argInfo中。
- 实现“文本型”返回值的命令
- CloneTextData 命令:[line:769]
- 注意指针的使用和释放。
- 实现“数组型”参数的命令:[line:1426]
- GetAryElementInf 命令:[line:825]
- 实现“通用型”参数的命令:[line:1290]
- 由于所有类型官方都提供了例子,所以课程不逐一介绍,具体请参见:
- [line:762] - [line:2023]
复制代码
- 易语言支持库第四课
- 再向支持库中添加一些“东西”
- 添加一个自定义数据类型
- 数据类型的定义:[line:2025]
- 窗口部分在后面的课程中进行介绍,本课主要研究普通数据类型。
- 数据类型中的方法定义:[line:2102]
- 注意:方法所属分类category必须为-1.
- 实现代码中,第一个参数始终为指向其所在数据类型的对象指针。
- 向数据类型中定义一个普通的成员:[line:2133]
- 参看:LIB_DATA_TYPE_ELEMENT定义。
- 扩展: 定义枚举变量[line:2060]
复制代码
- 支持库编写第五课:
- 窗口组件的定义: [line: 2253]
- 为了保证能够和官方核心库完整兼容,窗口定义部分使用 VC98 (6.0) 进行编写。
- 窗口组件也是一种数据类型,只是该数据类型被标记为窗口组件。
- 标记为窗口组件的组件需要额外实现一些方法、内容,才能确保程序显示正常。
- 下面来看具体的介绍:
- 如果为窗口组件,则在定义数据类型时,要特别注意下面这些:
- LIB_DATA_TYPE_INFO 中的 m_dwState, m_dwUnitBmpID, m_nEventCount, m_pEventBegin, m_nPropertyCount, m_pPropertyBegin, m_pfnGetInterface
- [line: 2025]
- 介绍unshare.h与unshare.cpp文件:
- 文件中包含了一些在编程中需要使用到的类,这里官方做了整理。直接调用便可。
- 额外需要注意的地方 [line:2992]
复制代码
- 支持库编写第六课:
- 编写一个“按钮”:
- 复习上一课:
- 通过支持库接口创建一个按钮,按钮应该继承自基类: CButton [line:2994]
- 重要的类:
- class CPIButton : public CPropertyInfo
- 属性类。 用来保存所有的组件相关的属性。 继承自 CPropertyInfo
- 需要实现: Init 初始化方法
- 需要实现: Serialize 用于在运行时应用属性
- #define ITF_CREATE_UNIT 1 // 创建单元
- 实现Create创建,用于创建窗口。
- -----------------------------------------------------------------------------
- 分别实现对应的“接口(GetInterface)”方法:[line: 2480]
- #define ITF_CREATE_UNIT 1 // 创建单元
- // 下面两个接口仅在可视化设计窗口界面时使用。
- #define ITF_PROPERTY_UPDATE_UI 2 // 说明属性目前可否被修改
- #define ITF_DLG_INIT_CUSTOMIZE_DATA 3 // 使用对话框设置自定义数据
- #define ITF_NOTIFY_PROPERTY_CHANGED 4 // 通知某属性数据被修改
- #define ITF_GET_ALL_PROPERTY_DATA 5 // 取全部属性数据
- #define ITF_GET_PROPERTY_DATA 6 // 取某属性数据
- 首先实现窗口的一些属性。
- 窗口属性的定义:
- 如果需要定义窗口的属性,则需要给m_nPropertyCount,m_pPropertyBegin赋值;
- 需要注意的地方是:在属性m_pPropertyBegin定义的最前面必须使用:FIXED_WIN_UNIT_PROPERTY([line:3431]),来填充基本的属性(左边,顶边,等)
- 属性的类型 [line:2287]
- 属性的修改 [line:2656]
- 属性的获取 [line:2706] [line:2757]
- 属性的应用
- ---
- 更多信息需要参考官方示例源码: HtmlView
- ////////////////////////////////////////////////////////////////////////////////////////////////////////
复制代码
- 持库编写第七课:
- 窗口组件的方法:
- 组件方法类似于自定义数据类型的方法,使用默认的定义即可。
- 编写方法的实现代码时要注意,此时第一个参数始终为指向其所在数据类型的对象指针
- 在方法中获取窗口类型指针。
- {
- GetWndPtr (pArgInf);
- }
- -----------------------
- 窗口组件的事件:
- 需要实现窗口组件的事件,首先需要定义事件、事件参数等。
- EVENT_INFO : [line:2419]
- EVENT_INFO2 : [line:2444]
- -
- EVENT_ARG_INFO : [line:2397]
- EVENT_ARG_INFO2 : [line:2413]
- 事件定义完毕后,将会在易语言设计界面中看到对应的事件,并且可以看到参数值等。
- -
- 触发窗口事件: [line:2917]
- 时间的触发,需要使用:EVENT_NOTIFY : [line:2926] 或 EVENT_NOTIFY2:[line:2945],来作为通知(NotifySys-NRS_EVENT_NOTIFY)的参数。
- ----------------------------------------------------------------------
- 更多内容请看代码。
复制代码
第八课:- 易语言静态支持库改造:
- 本课重点给大家讲解如何将易语言动态库转换为支持静态编译的易语言静态库。
- 首先看一下官方文档中对静态库的一些说明:
- 易语言5.0“基于第三方链接器的”静态编译方案的核心是:把易语言编译器生成的中间数据,编译成COFF格式的obj文件,然后把它交给第三方链接器,与各支持库的静态库(*.lib文件)一起链接生成EXE/DLL。
- 为了配合静态编译,易语言编译器、核心支持库、集成开发环境(IDE)均已做出重大更新,绝大多数官方支持库已完成自身改造。
- 第三方支持库需要作者按照本文介绍的方法完成支持库改造,以便支持静态编译。未经静态编译改造的原有支持库,仍可在新版易语言中使用,只是不能支持静态编译。
- 一、部分函数需要修改函数名称和符号导出方式
- 所有命令和方法的实现函数(PFN_EXECUTE_CMD)、处理系统通知的函数(PFN_NOTIFY_LIB),均需要修改函数名称,添加“库名称前缀”,并修改为以C符号形式导出(在C++中使用 extern "C");
- 所有数据类型的接口获取函数(PFN_GET_INTERFACE),需要统一命名为 <库名称前缀>_GetInterface_<数据类型英文名称>,并修改为以C符号形式导出(在C++中使用 extern "C");非窗口组件数据类型不需要接口获取函数。
- 二、在处理系统通知的函数中返回特定的信息
- 当通知参数为 NL_GET_CMD_FUNC_NAMES 时,应返回所有命令和方法实现函数的函数名称数组,此数组必须与命令和方法定义数组一一对应,数组各成员均为对应函数的函数名称文本指针(char*);
- 当通知参数为 NL_GET_NOTIFY_LIB_FUNC_NAME 时,应返回“处理系统通知的函数”(即自身函数)的函数名称(char*);
- 当通知参数为 NL_GET_DEPENDENT_LIBS 时,应返回“依赖的第三方静态库文件列表”,格式为\0分隔的文本,结尾两个\0。
- 三、从静态库中去除库定义相关的所有信息
- 与库定义有关的所有信息,包括命令和方法及其参数的定义信息、命令和方法的实现函数数组(m_pCmdsFunc)、数据类型及其属性事件方法的定义信息、GetNewInf()函数的定义等等,都不应该包含在静态库中。
- 从静态库中去除这些信息并不是必须的,但如果不去除,往往会造成链接时符号冲突,或导致链接生成的文件过大等一系列问题。
- 在静态库中,去除全局变量 theApp 的定义,代码中用到它之处,请替换为 AfxGetApp()。如果单纯替换为 AfxGetApp() 不能解决,需自行设法处理。这是必须的。
- 在静态库中,CWinApp继承类中的初始化和清理代码,可在一个static的全局类变量的构造和析构函数中调用;动态库中在GetNewInf()中的初始化代码,也可用类似方法解决。
- 在静态库中,应尽量减少导出符号对外部的影响,尽量定义为static符号,或添加自定义前缀。这有助于避免链接时的符号重复定义之类的链接错误。
- 四、使用符号重命名程序(resym.exe)来处理程序以减少名称冲突。
- 命令行:"C:\Program Files\e\sdk\tools\resym.exe" all infile="$(TargetPath)" outfile="$(TargetPath)"
- VC6.0中的具体操作
- 在原有支持库VC6工程(.dsw)的基础上,新建一个“Win32 Static Library”项目(.dsp),新项目名称为原项目名称后加"_static"(如 iext3_static)。建议把新项目文件创建在原项目文件旁边(两个项目在同一目录)。
- 进入创建项目下一步,不选择“Pre-Compiled header”,根据需要确定是否选择“MFC support”(如果暂时不确认,可以先选上,事后再取消)。
- 为新项目添加预定义宏 __E_STATIC_LIB,并把原项目中的源代码文件都添加进来(VC6文件视图(FileView)中支持 Ctrl+C Ctrl+V)。
复制代码
|
评分
-
查看全部评分
|