易语言高级进阶:混合编程、系统底层与开源生态拓展

易语言高级进阶:混合编程、系统底层与开源生态拓展

九、易语言高级进阶:混合编程、系统底层与开源生态拓展

在这里插入图片描述

9.1 引言

💡 前8篇我们从基础语法开始,逐步学习了组件库、本地存储、网络通信、数据库应用、多线程优化、高级组件使用、程序打包发布,最后完成了企业内部员工管理系统的大型项目实战。到这里,我们已经具备了开发复杂Windows桌面应用程序的能力。但在实际开发中,我们还会遇到一些更高级的需求,如需要调用C/C++的高性能算法需要操作系统底层需要开发Web应用需要使用开源库和框架等。

本章将重点讲解易语言的高级进阶方向,帮助大家解决这些高级需求:

  • 混合编程:易语言与C/C++、.NET等其他语言的混合编程方法
  • 系统底层编程:Windows API调用、钩子编程、进程/线程管理
  • Web开发:精易Web服务器的使用,写简单的后端API
  • 开源生态拓展:精易模块、其他开源支持库的介绍和使用
  • 高级调试技巧与性能优化:内存泄漏检测、CPU占用分析、代码优化的高级方法
  • 项目维护与重构:代码规范、版本控制、代码重构的方法
  • 未来展望:WebAssembly、跨平台开发、.NET互操作

通过学习本章内容,我们可以将易语言的应用范围拓展到高性能计算系统工具开发Web后端开发等领域,提升自己的开发水平。

9.1.1 学习目标

  • 掌握易语言与C/C++混合编程的方法(调用C/C++ DLL、易语言写DLL供其他语言调用)
  • 学会使用Windows API调用系统底层功能(获取系统信息、操作注册表、文件操作)
  • 了解钩子编程的基础概念和使用方法(键盘钩子、鼠标钩子)
  • 学会使用精易Web服务器搭建简单的Web后端API
  • 了解易语言的开源生态(精易模块、其他开源支持库)
  • 掌握高级调试技巧(内存泄漏检测、CPU占用分析)
  • 学会项目维护与重构的方法(代码规范、Git使用、代码重构)
  • 了解易语言的未来发展方向

9.1.2 学习重点

  • 易语言与C/C++混合编程的编译和调用步骤
  • Windows API调用的参数传递和返回值处理
  • 钩子编程的安装、使用和卸载
  • 精易Web服务器的路由配置和数据库操作
  • 精易模块的常用功能和使用方法
  • 内存泄漏检测工具的使用
  • Git版本控制的基础操作

9.2 易语言与C/C++混合编程

易语言支持调用其他语言写的DLL,也可以将自己的代码编译成DLL供其他语言调用。这使得易语言可以和C/C++、C#、Java等语言混合编程,充分发挥各自的优势。

9.2.1 调用C/C++写的DLL

C/C++语言具有高性能的特点,适合写复杂的算法、系统工具等。我们可以将这些功能封装成DLL,然后在易语言中调用。

1. C语言写DLL的步骤

创建C语言项目:打开Visual Studio,选择“Windows桌面向导”,项目类型选择“动态链接库(DLL)”
编写DLL函数:在dllmain.cpp文件中编写我们需要的函数
导出DLL函数:使用__declspec(dllexport)关键字导出函数
编译DLL:选择“Release”模式,编译项目,生成.dll.lib文件

C语言DLL代码示例:

// dllmain.cpp : 定义 DLL 应用程序的入口点。#include"pch.h"#include<stdio.h>#include<stdlib.h>#include<string.h> BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ){switch(ul_reason_for_call){case DLL_PROCESS_ATTACH:case DLL_THREAD_ATTACH:case DLL_THREAD_DETACH:case DLL_PROCESS_DETACH:break;}return TRUE;}// 简单的加法函数__declspec(dllexport)intAdd(int a,int b){return a + b;}// 字符串拼接函数__declspec(dllexport)char*StrCat(char* str1,char* str2){int len1 =strlen(str1);int len2 =strlen(str2);char* result =(char*)malloc(len1 + len2 +1);strcpy(result, str1);strcat(result, str2);return result;}// 释放内存函数(用于释放StrCat函数分配的内存)__declspec(dllexport)voidFreeMemory(char* ptr){if(ptr !=NULL){free(ptr); ptr =NULL;}}
2. 易语言调用DLL的步骤

将DLL文件复制到程序目录:将Visual Studio编译生成的.dll文件复制到易语言程序的目录下
声明DLL命令:在易语言中使用DLL命令关键字声明要调用的DLL函数
调用DLL函数:在代码中直接调用声明的DLL命令

易语言调用DLL代码示例:

.版本 2 .支持库 spec ' 声明DLL命令 .DLL命令 DLL_Add, 整数型, "TestDLL.dll", "Add" .参数 a, 整数型 .参数 b, 整数型 .DLL命令 DLL_StrCat, 整数型, "TestDLL.dll", "StrCat" .参数 str1, 文本型 .参数 str2, 文本型 .DLL命令 DLL_FreeMemory, , "TestDLL.dll", "FreeMemory" .参数 ptr, 整数型 .子程序 _btnAdd_被单击 .局部变量 结果, 整数型 ' 调用加法函数 结果 = DLL_Add (到数值 (txtA.内容), 到数值 (txtB.内容)) lblResult.标题 = “加法结果:” + 到文本 (结果) 调试输出 (“加法结果:”, 结果) .子程序 _btnStrCat_被单击 .局部变量 结果指针, 整数型 .局部变量 结果文本, 文本型 ' 调用字符串拼接函数 结果指针 = DLL_StrCat (txtStr1.内容, txtStr2.内容) 结果文本 = 指针到文本 (结果指针) lblResult.标题 = “字符串拼接结果:” + 结果文本 ' 调用释放内存函数 DLL_FreeMemory (结果指针) 调试输出 (“字符串拼接结果:”, 结果文本) 

9.2.2 易语言写DLL供其他语言调用

易语言也可以将自己的代码编译成DLL,供C/C++、C#、Java等语言调用。

1. 易语言写DLL的步骤

创建易语言DLL项目:打开易语言,选择“Windows动态链接库”项目类型
编写DLL函数:在程序集中编写我们需要的函数,使用_启动子程序DLL命令关键字
编译DLL:选择“静态编译”模式,编译项目,生成.dll文件

易语言DLL代码示例:

.版本 2 .支持库 spec ' 易语言DLL的启动子程序(必须存在) .子程序 _启动子程序, 整数型, , 本子程序在DLL初始化时会被自动调用 返回 (0) ' 简单的乘法函数(导出函数) .DLL命令 DLL_Multiply, 整数型, , "Multiply" .参数 a, 整数型 .参数 b, 整数型 .子程序 Multiply, 整数型 .参数 a, 整数型 .参数 b, 整数型 返回 (a × b) ' 计算字符串长度函数(导出函数) .DLL命令 DLL_StrLen, 整数型, , "StrLen" .参数 str, 文本型 .子程序 StrLen, 整数型 .参数 str, 文本型 返回 (取文本长度 (str)) 
2. C语言调用易语言写的DLL的步骤

将易语言编译生成的DLL文件复制到程序目录:将易语言编译生成的.dll文件复制到C语言程序的目录下
声明DLL函数:在C语言中使用__declspec(dllimport)关键字声明要调用的DLL函数
调用DLL函数:在代码中直接调用声明的DLL函数

C语言调用易语言DLL代码示例:

#include<stdio.h>#include<stdlib.h>#include<windows.h>// 声明易语言DLL函数__declspec(dllimport)intMultiply(int a,int b);__declspec(dllimport)intStrLen(char* str);intmain(){// 调用乘法函数int multiplyResult =Multiply(10,20);printf("乘法结果:%d\n", multiplyResult);// 调用字符串长度函数char* str ="Hello, World!";int strLenResult =StrLen(str);printf("字符串长度:%d\n", strLenResult);system("pause");return0;}

9.3 系统底层编程基础

Windows系统提供了大量的API(应用程序编程接口),我们可以通过调用这些API来操作系统底层功能,如获取系统信息、操作注册表、文件操作、进程/线程管理等。

9.3.1 Windows API调用基础

在易语言中,我们可以使用DLL命令关键字来调用Windows API。Windows API的函数名通常以GetSetCreateDelete等前缀开头,参数和返回值的类型通常是整数型文本型字节集等。

获取系统信息代码示例:

.版本 2 .支持库 spec ' 声明Windows API函数 .DLL命令 GetSystemInfo, , "kernel32.dll", "GetSystemInfo" .参数 lpSystemInfo, 系统信息, 传址 ' 系统信息结构体 .数据类型 系统信息 .成员 dwOemId, 大整数型 .成员 dwPageSize, 大整数型 .成员 lpMinimumApplicationAddress, 大整数型 .成员 lpMaximumApplicationAddress, 大整数型 .成员 dwActiveProcessorMask, 大整数型 .成员 dwNumberOfProcessors, 大整数型 .成员 dwProcessorType, 大整数型 .成员 dwAllocationGranularity, 大整数型 .成员 wProcessorLevel, 短整数型 .成员 wProcessorRevision, 短整数型 .子程序 _btnGetSystemInfo_被单击 .局部变量 系统信息, 系统信息 .局部变量 处理器数量, 整数型 .局部变量 处理器类型, 文本型 ' 调用GetSystemInfo函数获取系统信息 GetSystemInfo (系统信息) ' 读取系统信息 处理器数量 = 系统信息.dwNumberOfProcessors .判断开始 (系统信息.dwProcessorType = 386) 处理器类型 = “Intel 80386” .判断 (系统信息.dwProcessorType = 486) 处理器类型 = “Intel 80486” .判断 (系统信息.dwProcessorType = 586) 处理器类型 = “Intel Pentium” .判断 (系统信息.dwProcessorType = 2200) 处理器类型 = “Intel IA-64” .判断 (系统信息.dwProcessorType = 8664) 处理器类型 = “AMD64或Intel EM64T” .默认 处理器类型 = “未知” .判断结束 ' 显示系统信息 lblSystemInfo.标题 = “处理器数量:” + 到文本 (处理器数量) + “ 个,处理器类型:” + 处理器类型 调试输出 (“处理器数量:”, 处理器数量, “ 个,处理器类型:”, 处理器类型) 

9.3.2 钩子编程

钩子编程是一种Windows系统提供的机制,允许应用程序在系统消息传递过程中截获并处理特定的消息。钩子可以分为全局钩子局部钩子,全局钩子可以截获整个系统的消息,局部钩子只能截获特定进程的消息。

键盘钩子代码示例(用于学习,不要用于非法用途):

.版本 2 .支持库 spec ' 声明Windows API函数 .DLL命令 SetWindowsHookEx, 整数型, "user32.dll", "SetWindowsHookExA" .参数 idHook, 整数型 .参数 lpfn, 子程序指针 .参数 hmod, 整数型 .参数 dwThreadId, 整数型 .DLL命令 UnhookWindowsHookEx, 逻辑型, "user32.dll", "UnhookWindowsHookEx" .参数 hhk, 整数型 .DLL命令 CallNextHookEx, 整数型, "user32.dll", "CallNextHookEx" .参数 hhk, 整数型 .参数 nCode, 整数型 .参数 wParam, 整数型 .参数 lParam, 整数型 ' 钩子句柄 .程序集变量 g_HookHandle, 整数型 ' 键盘钩子回调函数 .子程序 KeyboardHookProc, 整数型, 公开 .参数 nCode, 整数型 .参数 wParam, 整数型 .参数 lParam, 整数型 .局部变量 键盘状态, 字节集 .局部变量 字符, 字节集 .局部变量 消息, 文本型 ' 如果nCode小于0,直接调用下一个钩子 .如果真 (nCode < 0) 返回 (CallNextHookEx (g_HookHandle, nCode, wParam, lParam)) .如果真结束 ' 处理键盘消息 .如果真 (wParam ≥ 0x30 且 wParam ≤ 0x5A) ' 数字和字母 消息 = 到文本 (字符 (wParam)) .如果真结束 .如果真 (wParam ≥ 0x60 且 wParam ≤ 0x6F) ' 小键盘数字 消息 = 到文本 (字符 (wParam - 0x30)) .如果真结束 .如果真 (wParam = 0x08) ' 退格键 消息 = “[退格键]” .如果真结束 .如果真 (wParam = 0x09) ' Tab键 消息 = “[Tab键]” .如果真结束 .如果真 (wParam = 0x0D) ' 回车键 消息 = “[回车键]” .如果真结束 .如果真 (wParam = 0x1B) ' Esc键 消息 = “[Esc键]” .如果真结束 ' 显示键盘消息 edtKeyboardMsg.内容 = edtKeyboardMsg.内容 + 消息 ' 调用下一个钩子 返回 (CallNextHookEx (g_HookHandle, nCode, wParam, lParam)) .子程序 _btnInstallHook_被单击 ' 安装键盘钩子 g_HookHandle = SetWindowsHookEx (13, &KeyboardHookProc, 0, 0) .如果真 (g_HookHandle = 0) 信息框 (“键盘钩子安装失败!”, 0, “错误提示”) 返回 () .如果真结束 btnInstallHook.禁止 = #真 btnUninstallHook.禁止 = #假 调试输出 (“键盘钩子安装成功!钩子句柄:”, g_HookHandle) .子程序 _btnUninstallHook_被单击 ' 卸载键盘钩子 UnhookWindowsHookEx (g_HookHandle) g_HookHandle = 0 btnInstallHook.禁止 = #假 btnUninstallHook.禁止 = #真 调试输出 (“键盘钩子卸载成功!”) 

9.3.3 进程/线程管理

进程是程序的实例,每个进程有自己的地址空间和资源;线程是程序执行的最小单位,每个线程有自己的栈和程序计数器。我们可以通过Windows API来管理进程和线程,如枚举进程、结束进程、创建线程等。

枚举进程代码示例:

.版本 2 .支持库 spec ' 声明Windows API函数 .DLL命令 CreateToolhelp32Snapshot, 整数型, "kernel32.dll", "CreateToolhelp32Snapshot" .参数 dwFlags, 整数型 .参数 th32ProcessID, 整数型 .DLL命令 Process32First, 逻辑型, "kernel32.dll", "Process32First" .参数 hSnapshot, 整数型 .参数 lppe, 进程信息, 传址 .DLL命令 Process32Next, 逻辑型, "kernel32.dll", "Process32Next" .参数 hSnapshot, 整数型 .参数 lppe, 进程信息, 传址 .DLL命令 CloseHandle, 逻辑型, "kernel32.dll", "CloseHandle" .参数 hObject, 整数型 ' 进程信息结构体 .数据类型 进程信息 .成员 dwSize, 大整数型 .成员 cntUsage, 大整数型 .成员 th32ProcessID, 大整数型 .成员 th32DefaultHeapID, 大整数型 .成员 th32ModuleID, 大整数型 .成员 cntThreads, 大整数型 .成员 th32ParentProcessID, 大整数型 .成员 pcPriClassBase, 大整数型 .成员 dwFlags, 大整数型 .成员 szExeFile, 字节集, , , 260 .子程序 _btnEnumProcess_被单击 .局部变量 快照句柄, 整数型 .局部变量 进程信息, 进程信息 .局部变量 是否继续, 逻辑型 ' 创建进程快照 快照句柄 = CreateToolhelp32Snapshot (2, 0) .如果真 (快照句柄 = -1) 信息框 (“进程快照创建失败!”, 0, “错误提示”) 返回 () .如果真结束 ' 初始化进程信息结构体 进程信息.dwSize = 取字节集长度 (进程信息) ' 枚举第一个进程 是否继续 = Process32First (快照句柄, 进程信息) .判断循环首 (是否继续) ' 显示进程信息 lstProcess.插入表项 (, ) lstProcess.置标题 (lstProcess.取表项数 () - 1, 0, 到文本 (进程信息.th32ProcessID)) ' 进程ID lstProcess.置标题 (lstProcess.取表项数 () - 1, 1, 到文本 (进程信息.cntThreads)) ' 线程数量 lstProcess.置标题 (lstProcess.取表项数 () - 1, 2, 到文本 (进程信息.szExeFile)) ' 进程名称 ' 枚举下一个进程 是否继续 = Process32Next (快照句柄, 进程信息) .判断循环尾 () ' 关闭进程快照 CloseHandle (快照句柄) 调试输出 (“进程枚举成功!数量:”, lstProcess.取表项数 ()) 

9.4 易语言Web开发

易语言主要是Windows桌面应用开发语言,但我们可以使用精易Web服务器来搭建简单的Web后端API,供前端(如HTML、Vue、React)调用。

9.4.1 精易Web服务器介绍

精易Web服务器是精易模块提供的一个Web服务器组件,基于Go语言开发,轻量、高性能、易用。我们可以使用精易Web服务器来处理HTTP请求,如GET、POST、PUT、DELETE等,操作数据库,返回JSON数据。

9.4.2 搭建简单的Web后端API

1. 安装精易Web服务器

① 打开精易论坛(https://bbs.125.la/),下载最新版本的精易模块
② 解压后,将“精易模块.ec”和“精易Web服务器.exe”文件复制到易语言的“lib”目录下(如C:\Program Files (x86)\易语言5.85\lib)
③ 打开易语言,点击“工具→支持库配置→全部支持库”,找到“精易模块”并勾选
④ 重启易语言

2. 编写Web后端API代码
.版本 2 .支持库 spec .支持库 eDB ' MySQL数据库连接句柄 .程序集变量 g_MySQL连接句柄, 整数型 .子程序 __启动窗口_创建完毕 ' 初始化组件属性 _启动窗口.标题 = “易语言Web服务器” _启动窗口.宽度 = 600 _启动窗口.高度 = 400 _启动窗口.左边 = (取屏幕宽度 () - _启动窗口.宽度) ÷ 2 _启动窗口.顶边 = (取屏幕高度 () - _启动窗口.高度) ÷ 2 ' 连接MySQL数据库 连接MySQL数据库 () ' 启动精易Web服务器 启动Web服务器 () 调试输出 (“Web服务器启动成功!访问地址:http://localhost:8080”) .子程序 连接MySQL数据库 .局部变量 服务器IP, 文本型 .局部变量 服务器端口, 整数型 .局部变量 用户名, 文本型 .局部变量 密码, 文本型 .局部变量 数据库名, 文本型 ' 从配置文件中读取数据库连接参数 服务器IP = 配置文件_取文本 (“Database”, “Host”, “127.0.0.1”) 服务器端口 = 到数值 (配置文件_取文本 (“Database”, “Port”, “3306”)) 用户名 = 配置文件_取文本 (“Database”, “User”, “root”) 密码 = 解密文本 (配置文件_取文本 (“Database”, “Password”, “e10adc3949ba59abbe56e057f20f883e”)) ' 默认密码:123456 数据库名 = 配置文件_取文本 (“Database”, “Name”, “emp_management”) ' 连接MySQL数据库 g_MySQL连接句柄 = MySQL.连接 (服务器IP, 服务器端口, 用户名, 密码, 数据库名) .如果真 (g_MySQL连接句柄 = 0) 信息框 (“数据库连接失败!错误信息:” + MySQL.取错误信息 (g_MySQL连接句柄), 0, “错误提示”) 返回 () .如果真结束 调试输出 (“MySQL数据库连接成功!”) .子程序 解密文本, 文本型 .参数 加密文本, 文本型 ' 简单的解密算法(实际开发中应该使用更安全的加密算法) 返回 (子文本替换 (加密文本, “加密前缀”, “”, , , 真)) .子程序 启动Web服务器 .局部变量 Web服务器, 类_Web服务器 ' 配置Web服务器 Web服务器.端口 = 8080 Web服务器.超时 = 30000 ' 添加路由 Web服务器.添加路由 (“GET”, “/api/employees”, &获取员工列表) Web服务器.添加路由 (“GET”, “/api/employees/(\d+)”, &获取员工详情) Web服务器.添加路由 (“POST”, “/api/employees”, &添加员工) Web服务器.添加路由 (“PUT”, “/api/employees/(\d+)”, &修改员工) Web服务器.添加路由 (“DELETE”, “/api/employees/(\d+)”, &删除员工) ' 启动Web服务器 Web服务器.启动 () 调试输出 (“Web服务器启动成功!”) .子程序 获取员工列表, 文本型, 公开 .参数 请求, 类_Web请求 .参数 响应, 类_Web响应 .局部变量 SQL语句, 文本型 .局部变量 记录集, 类_记录集 .局部变量 员工列表, 文本型 .局部变量 i, 整数型 ' 查询员工列表 SQL语句 = “SELECT emp_id, emp_no, emp_name, gender, birthday, id_card, phone, email, address, dept_id, position, entry_time, leave_time, status FROM emp WHERE status = 1 ORDER BY emp_id ASC” 记录集 = MySQL.查询 (g_MySQL连接句柄, SQL语句) ' 构建JSON数据 员工列表 = “{”“code”“: 200, ”“msg”“: ”“查询成功”“, ”“data”“: [” .判断循环首 (记录集.到记录尾 () = #假) .如果真 (i > 0) 员工列表 = 员工列表 + “,” .如果真结束 员工列表 = 员工列表 + “{” 员工列表 = 员工列表 + “”“emp_id”“: ” + 到文本 (记录集.读大整数 (“emp_id”)) + “, ” 员工列表 = 员工列表 + “”“emp_no”“: ”“”“ + 记录集.读文本 (“emp_no”) + “”“ + “, ” 员工列表 = 员工列表 + “”“emp_name”“: ”“”“ + 记录集.读文本 (“emp_name”) + “”“ + “, ” 员工列表 = 员工列表 + “”“gender”“: ” + 到文本 (记录集.读整数 (“gender”)) + “, ” 员工列表 = 员工列表 + “”“birthday”“: ”“”“ + 到文本 (记录集.读日期 (“birthday”), , “yyyy-MM-dd”) + “”“ + “, ” 员工列表 = 员工列表 + “”“id_card”“: ”“”“ + 记录集.读文本 (“id_card”) + “”“ + “, ” 员工列表 = 员工列表 + “”“phone”“: ”“”“ + 记录集.读文本 (“phone”) + “”“ + “, ” 员工列表 = 员工列表 + “”“email”“: ”“”“ + 记录集.读文本 (“email”) + “”“ + “, ” 员工列表 = 员工列表 + “”“address”“: ”“”“ + 记录集.读文本 (“address”) + “”“ + “, ” 员工列表 = 员工列表 + “”“dept_id”“: ” + 到文本 (记录集.读大整数 (“dept_id”)) + “, ” 员工列表 = 员工列表 + “”“position”“: ”“”“ + 记录集.读文本 (“position”) + “”“ + “, ” 员工列表 = 员工列表 + “”“entry_time”“: ”“”“ + 到文本 (记录集.读日期 (“entry_time”), , “yyyy-MM-dd”) + “”“ + “, ” 员工列表 = 员工列表 + “”“leave_time”“: ” + iif (记录集.读日期 (“leave_time”) = #空日期, “null”, “”“ + 到文本 (记录集.读日期 (“leave_time”), , “yyyy-MM-dd”) + “”“) + “, ” 员工列表 = 员工列表 + “”“status”“: ” + 到文本 (记录集.读整数 (“status”)) 员工列表 = 员工列表 + “}” i = i + 1 记录集.到下一条 () .判断循环尾 () 员工列表 = 员工列表 + “]}” ' 关闭记录集 记录集.关闭 () ' 返回JSON数据 响应.内容类型 = “application/json” 响应.内容 = 员工列表 返回 (员工列表) .子程序 获取员工详情, 文本型, 公开 .参数 请求, 类_Web请求 .参数 响应, 类_Web响应 .局部变量 员工ID, 大整数型 .局部变量 SQL语句, 文本型 .局部变量 记录集, 类_记录集 .局部变量 员工详情, 文本型 ' 获取员工ID 员工ID = 到数值 (请求.路由参数 [0]) ' 查询员工详情 SQL语句 = “SELECT emp_id, emp_no, emp_name, gender, birthday, id_card, phone, email, address, dept_id, position, entry_time, leave_time, status FROM emp WHERE emp_id = ” + 到文本 (员工ID) 记录集 = MySQL.查询 (g_MySQL连接句柄, SQL语句) .如果真 (记录集.记录数量 = 0) ' 员工不存在 响应.内容类型 = “application/json” 响应.内容 = “{”“code”“: 404, ”“msg”“: ”“员工不存在”“, ”“data”“: null}” 记录集.关闭 () 返回 (响应.内容) .如果真结束 ' 构建JSON数据 员工详情 = “{”“code”“: 200, ”“msg”“: ”“查询成功”“, ”“data”“: {” 员工详情 = 员工详情 + “”“emp_id”“: ” + 到文本 (记录集.读大整数 (“emp_id”)) + “, ” 员工详情 = 员工详情 + “”“emp_no”“: ”“”“ + 记录集.读文本 (“emp_no”) + “”“ + “, ” 员工详情 = 员工详情 + “”“emp_name”“: ”“”“ + 记录集.读文本 (“emp_name”) + “”“ + “, ” 员工详情 = 员工详情 + “”“gender”“: ” + 到文本 (记录集.读整数 (“gender”)) + “, ” 员工详情 = 员工详情 + “”“birthday”“: ”“”“ + 到文本 (记录集.读日期 (“birthday”), , “yyyy-MM-dd”) + “”“ + “, ” 员工详情 = 员工详情 + “”“id_card”“: ”“”“ + 记录集.读文本 (“id_card”) + “”“ + “, ” 员工详情 = 员工详情 + “”“phone”“: ”“”“ + 记录集.读文本 (“phone”) + “”“ + “, ” 员工详情 = 员工详情 + “”“email”“: ”“”“ + 记录集.读文本 (“email”) + “”“ + “, ” 员工详情 = 员工详情 + “”“address”“: ”“”“ + 记录集.读文本 (“address”) + “”“ + “, ” 员工详情 = 员工详情 + “”“dept_id”“: ” + 到文本 (记录集.读大整数 (“dept_id”)) + “, ” 员工详情 = 员工详情 + “”“position”“: ”“”“ + 记录集.读文本 (“position”) + “”“ + “, ” 员工详情 = 员工详情 + “”“entry_time”“: ”“”“ + 到文本 (记录集.读日期 (“entry_time”), , “yyyy-MM-dd”) + “”“ + “, ” 员工详情 = 员工详情 + “”“leave_time”“: ” + iif (记录集.读日期 (“leave_time”) = #空日期, “null”, “”“ + 到文本 (记录集.读日期 (“leave_time”), , “yyyy-MM-dd”) + “”“) + “, ” 员工详情 = 员工详情 + “”“status”“: ” + 到文本 (记录集.读整数 (“status”)) 员工详情 = 员工详情 + “}}” ' 关闭记录集 记录集.关闭 () ' 返回JSON数据 响应.内容类型 = “application/json” 响应.内容 = 员工详情 返回 (员工详情) 

9.4.3 测试Web后端API

我们可以使用Postmancurl工具来测试Web后端API。

使用Postman测试获取员工列表API:
① 打开Postman,选择“GET”请求方式
② 输入访问地址:http://localhost:8080/api/employees
③ 点击“Send”按钮,查看响应结果

使用curl测试获取员工列表API:

curl -X GET http://localhost:8080/api/employees 

9.5 开源生态拓展

易语言有一个活跃的开源社区,提供了大量的开源库和框架,如精易模块EasyExcel支持库EasyPDF支持库EasyChart支持库等。这些开源库和框架可以帮助我们提高开发效率,减少重复代码的编写。

9.5.1 精易模块

精易模块是易语言社区最受欢迎的开源库之一,提供了大量的常用功能,如字符串处理、文件操作、网络通信、数据库操作、GUI组件、Web服务器、正则表达式等。

精易模块的常用功能
  1. 字符串处理:精易模块提供了大量的字符串处理函数,如字符串替换、字符串分割、字符串拼接、字符串加密、字符串解密等
  2. 文件操作:精易模块提供了大量的文件操作函数,如文件创建、文件删除、文件重命名、文件复制、文件读写、文件夹遍历等
  3. 网络通信:精易模块提供了大量的网络通信函数,如HTTP访问、Socket通信、FTP访问、邮件发送等
  4. 数据库操作:精易模块提供了MySQL、SQLite、SQL Server等数据库的操作函数
  5. GUI组件:精易模块提供了高级表格、树型框、RichEdit编辑框、进度条组件等高级GUI组件的使用方法
  6. Web服务器:精易模块提供了精易Web服务器组件,可以搭建简单的Web后端API
  7. 正则表达式:精易模块提供了正则表达式的使用方法,可以用于字符串匹配、替换等
精易模块的使用方法

① 下载并安装精易模块(参考9.4.1)
② 打开易语言,点击“工具→支持库配置→全部支持库”,找到“精易模块”并勾选
③ 在代码中直接调用精易模块的函数

精易模块字符串处理代码示例:

.版本 2 .支持库 spec .支持库 eJYM .子程序 _btnStrReplace_被单击 .局部变量 原文本, 文本型 .局部变量 旧文本, 文本型 .局部变量 新文本, 文本型 .局部变量 替换结果, 文本型 ' 获取输入 原文本 = txtOriginal.内容 旧文本 = txtOld.内容 新文本 = txtNew.内容 ' 使用精易模块的字符串替换函数 替换结果 = 文本_替换 (原文本, 旧文本, 新文本, , , 真) ' 显示替换结果 edtResult.内容 = 替换结果 调试输出 (“字符串替换结果:”, 替换结果) 

9.5.2 其他开源支持库

除了精易模块,易语言社区还有其他大量的开源支持库,如:

  1. EasyExcel支持库:用于操作Excel文件,支持读取、写入、修改Excel文件
  2. EasyPDF支持库:用于操作PDF文件,支持创建、读取、修改PDF文件
  3. EasyChart支持库:用于生成图表,支持柱状图、饼图、折线图等
  4. EasySocket支持库:用于Socket通信,支持TCP、UDP协议
  5. EasyEmail支持库:用于发送邮件,支持SMTP、POP3协议

9.6 高级调试技巧与性能优化

程序开发过程中肯定会遇到各种bug和性能问题,掌握高级调试技巧和性能优化方法可以提高开发效率和程序的质量。

9.6.1 内存泄漏检测

内存泄漏是程序运行时常见的问题,会导致程序的内存占用不断增加,最终崩溃。我们可以使用Windows Debug ToolsProcess Explorer来检测内存泄漏。

使用Windows Debug Tools检测内存泄漏

① 下载并安装Windows Debug Tools(https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk/)
② 打开gflags.exe工具,设置要检测的程序的内存泄漏检测标志
③ 运行程序,执行可能导致内存泄漏的操作
④ 打开windbg.exe工具,加载程序的调试信息,使用!heap命令检测内存泄漏

使用Process Explorer检测内存泄漏

① 下载并安装Process Explorer(https://docs.microsoft.com/en-us/sysinternals/downloads/process-explorer)
② 运行Process Explorer,找到要检测的程序
③ 观察程序的内存占用情况,如果内存占用不断增加,说明可能存在内存泄漏

9.6.2 CPU占用分析

CPU占用过高是程序运行时常见的性能问题,会导致程序运行缓慢、界面卡顿。我们可以使用Windows Performance AnalyzerProcess Explorer来分析CPU占用情况。

使用Windows Performance Analyzer分析CPU占用

① 下载并安装Windows Performance Analyzer(https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk/)
② 打开Windows Performance Recorder,选择“CPU Usage”场景,开始录制
③ 运行程序,执行可能导致CPU占用过高的操作
④ 停止录制,打开录制文件,使用Windows Performance Analyzer分析CPU占用情况

使用Process Explorer分析CPU占用

① 下载并安装Process Explorer(https://docs.microsoft.com/en-us/sysinternals/downloads/process-explorer)
② 运行Process Explorer,找到要分析的程序
③ 观察程序的CPU占用情况,如果CPU占用过高,说明可能存在性能问题

9.6.3 代码优化的高级方法

除了基础的代码优化方法,还有一些高级的代码优化方法,如:

  1. 循环展开:将循环体内的代码复制多次,减少循环的次数
  2. 内存对齐:将数据结构的成员对齐到特定的内存边界,提高内存访问效率
  3. 内联函数:将函数的代码复制到调用的地方,减少函数调用的开销
  4. 缓存优化:使用数组代替链表,减少内存访问的次数
  5. 并行计算:使用多线程或GPU进行并行计算,提高程序的运行效率

9.7 项目维护与重构

项目维护与重构是软件开发的重要环节,一个好的项目维护和重构方法可以提高程序的可维护性和可扩展性。

9.7.1 代码规范

代码规范是项目维护的基础,一个好的代码规范可以提高代码的可读性和可维护性。易语言社区有一些常用的代码规范,如:

  1. 变量命名规范:使用有意义的变量名,避免使用单个字母或无意义的变量名
  2. 函数命名规范:使用动词+名词的方式命名函数,如获取员工列表添加员工
  3. 注释规范:在关键代码处添加注释,解释代码的功能和实现思路
  4. 代码格式化规范:统一代码的缩进、空格、换行等格式

9.7.2 版本控制

版本控制是项目维护的重要工具,我们可以使用Git来管理项目的版本。Git可以帮助我们:

  1. 记录项目的历史版本
  2. 恢复到历史版本
  3. 比较不同版本的代码差异
  4. 协作开发
Git的基础操作
  1. 初始化仓库:使用git init命令初始化一个新的Git仓库
  2. 添加文件:使用git add命令将文件添加到暂存区
  3. 提交文件:使用git commit命令将暂存区的文件提交到仓库
  4. 查看日志:使用git log命令查看提交日志
  5. 创建分支:使用git branch命令创建一个新的分支
  6. 切换分支:使用git checkout命令切换到新的分支
  7. 合并分支:使用git merge命令合并分支

9.7.3 代码重构

代码重构是项目维护的重要手段,我们可以通过代码重构来提高程序的可维护性和可扩展性。常用的代码重构方法有:

  1. 提取函数:将重复的代码提取到一个新的函数中
  2. 提取类:将相关的函数和数据提取到一个新的类中
  3. 重命名变量:将无意义的变量名重命名为有意义的变量名
  4. 拆分函数:将过长的函数拆分成多个小函数
  5. 合并函数:将功能相似的函数合并成一个函数

9.8 易语言的未来展望

易语言虽然主要是Windows桌面应用开发语言,但随着技术的发展,易语言的应用范围也在不断拓展。未来,易语言可能会支持:

  1. WebAssembly:将易语言代码编译成WebAssembly,在浏览器中运行
  2. 跨平台开发:使用Linux下的Wine或者其他工具,让易语言程序在Linux和Mac OS系统上运行
  3. .NET互操作:调用C#写的DLL,或者将易语言代码编译成.NET程序集
  4. 移动应用开发:开发移动应用,支持Android和iOS系统

9.9 总结

✅ 本章详细介绍了易语言的高级进阶方向,包括混合编程系统底层编程Web开发开源生态拓展高级调试技巧与性能优化项目维护与重构未来展望。通过学习,我们掌握了:

  • 易语言与C/C++混合编程的方法(调用C/C++ DLL、易语言写DLL供其他语言调用)
  • Windows API调用的基础概念和使用方法(获取系统信息、操作注册表、文件操作)
  • 钩子编程的基础概念和使用方法(键盘钩子、鼠标钩子)
  • 精易Web服务器的使用方法,搭建简单的Web后端API
  • 易语言的开源生态(精易模块、其他开源支持库)
  • 高级调试技巧(内存泄漏检测、CPU占用分析)
  • 项目维护与重构的方法(代码规范、Git使用、代码重构)
  • 易语言的未来发展方向

易语言的高级进阶方向是一个不断探索和学习的过程,希望大家能够认真学习本章内容,多动手实践,理解高级进阶的核心原理,为后续开发更复杂的应用程序打下坚实的基础。

Read more

极致性能的服务器Redis之Hash类型及相关指令介绍

极致性能的服务器Redis之Hash类型及相关指令介绍

目录 1. Hash介绍 2. hset 3. hget 3. hdel 5. hkeys 6. hvals 编辑 7. hgetall  8. hexists 9. hmget 10. hlen 11. hsetnx 12. hincrby 13. hincrbyfloat 1. Hash介绍 Redis 哈希类型是键值对的集合,字段与值均支持字符串、数字等类型,适合建模用户信息、配置项等对象类数据。其支持单字段 / 多字段的增删改查、字段存在性判断、值自增自减等原子操作,且底层通过压缩列表或哈希表优化存储,空间利用率高、查询效率快,是 Redis 中存储结构化数据的核心类型之一。 在Redis中因为本身就是按照哈希的KV结构来进行存储的,所以当我们想要使用Redis里面的哈希的时候,实际上是哈希的哈希,在后者中,

By Ne0inhk
《算法题讲解指南:优选算法-二分查找》--23.寻找旋转排序数组中的最小值,24.0~n-1中缺失的数字

《算法题讲解指南:优选算法-二分查找》--23.寻找旋转排序数组中的最小值,24.0~n-1中缺失的数字

🔥小叶-duck:个人主页 ❄️个人专栏:《Data-Structure-Learning》 《C++入门到进阶&自我学习过程记录》《算法题讲解指南》--从优选到贪心 ✨未择之路,不须回头 已择之路,纵是荆棘遍野,亦作花海遨游 目录 23.寻找旋转排序数组中的最小值 题目链接: 题目描述: 题目示例: 解法(二分查找): 算法思路: C++算法代码:(以nums[ n - 1 ]为参照物) C++算法代码:(以nums[ 0 ]为参照物) 算法总结及流程解析: 24.0~n-1中缺失的数字 题目链接: 题目描述: 题目示例: 解法(二分查找): 算法思路: C++算法代码: 算法总结及流程解析: 结束语

By Ne0inhk
《二分查找:从 “折半” 到 “精准命中” 的算法逻辑拆解》

《二分查找:从 “折半” 到 “精准命中” 的算法逻辑拆解》

前引:算法面试中,二分查找是 “高频考点” 之一,它不仅能考察求职者的逻辑思维,还能检验对时间复杂度优化的理解。而在实际开发中,二分查找更是处理 “有序数据查找” 问题的最优解无论是缓存查找、数据索引,还是参数优化,都能看到它的身影。但很多开发者对二分查找的理解停留在 “基础用法”,忽略了其在复杂场景下的拓展应用,也未能规避常见的边界错误。本文将结合面试真题和实战案例,全面解析二分查找的原理、优化技巧、场景延伸,帮你既能轻松应对面试,又能在实际开发中高效运用,真正发挥二分查找的 “效率优势”! 目录 【一】“二分”算法原理剖析 【二】简单的二分查找 (1)题目链接 (2)算法解析 【三】找目标范围 (1)题目链接 (2)算法解析 (3)代码 【四】搜索插入位置 (1)题目链接 (2)算法解析

By Ne0inhk
Ubuntu系统下Python连接国产KingbaseES数据库实现增删改查

Ubuntu系统下Python连接国产KingbaseES数据库实现增删改查

摘要:本文将介绍Ubuntu系统下如何使用Python连接国产金仓数据库KingbaseES,并实现基本的增删改查操作。文中将通过具体代码示例展示连接数据库、执行SQL语句以及处理结果的全过程。这里把Python连接KingbaseES的经验整理一下,希望能帮到同样踩坑的兄弟。 目录 1.环境准备与驱动安装 1.1 科普ksycopg2知识 1.2 官方下载ksycopg2驱动 1.3 安装ksycopg2驱动 2. 连接KingbaseES数据库 3. 创建数据表 4. 实现增删改查功能 4.1 新增 4.2 查询 4.3 修改 4.4 删除 4.5 封装一个类crud方便复用 5.总结 1.环境准备与驱动安装 KingbaseES提供了专门的Python驱动包ksycopg2,它是基于Python DB API 2.0规范实现的线程安全数据库适配器!

By Ne0inhk