Lua中文语言编程源码-第五节,更改lcorolib.c协程库函数, 使Lua加载中文库关键词(与所有的基础库相关)
源码已经更新在CSDN的码库里:
git clone https://gitcode.com/funsion/CLua.git
在src文件夹下的lcorolib.c协程库函数,Coroutine Library
:表明这个C源文件实现了Lua的协程库(Coroutine Library),即提供了与协程相关的API和功能实现。
增加中文版协程函数名列表,保留英文版协程函数名列表。
原始的代码为:
static const luaL_Reg co_funcs[] = {
{"create", luaB_cocreate},
{"resume", luaB_coresume},
{"running", luaB_corunning},
{"status", luaB_costatus},
{"wrap", luaB_cowrap},
{"yield", luaB_yield},
{"isyieldable", luaB_yieldable},
{"close", luaB_close},
{NULL, NULL}
};
更改成以下代码:
/*
* 协程功能的注册表
* 该表包含了所有协程相关函数的英文名和中文名,以及它们对应的实现函数。
* 该注册表用于在Lua中注册这些协程函数,以便于在Lua脚本中调用。
*/
static const luaL_Reg co_funcs[] = {
/* 英文版协程函数名 */
{"create", luaB_cocreate}, /* 创建一个新的协程 */
{"resume", luaB_coresume}, /* 恢复一个协程的执行 */
{"running", luaB_corunning}, /* 获取当前正在运行的协程 */
{"status", luaB_costatus}, /* 获取一个协程的状态 */
{"wrap", luaB_cowrap}, /* 将一个函数封装成一个协程 */
{"yield", luaB_yield}, /* 使当前协程挂起 */
{"isyieldable", luaB_yieldable}, /* 检查当前协程是否可以挂起 */
{"close", luaB_close}, /* 关闭一个协程 */
/* 中文版协程函数名 */
{"创建", luaB_cocreate}, /* 创建一个新的协程 */
{"恢复", luaB_coresume}, /* 恢复一个协程的执行 */
{"程名", luaB_corunning}, /* 获取当前正在运行的协程 */
{"状态", luaB_costatus}, /* 获取一个协程的状态 */
{"程包", luaB_cowrap}, /* 将一个函数封装成一个协程 */
{"挂起", luaB_yield}, /* 使当前协程挂起 */
{"可挂起", luaB_yieldable}, /* 检查当前协程是否可以挂起 */
{"关闭", luaB_close}, /* 关闭一个协程 */
{NULL, NULL} /* 注册表结束标志 */
};
为了保证中英文协程函数都可以加载,以便你可以复制英文原码来进行更改。所以保留了英文版协程函数名列表,这样就能使用两种文的函数。
{"create", luaB_cocreate}, /* 创建一个新的协程 */
{"创建", luaB_cocreate}, /* 创建一个新的协程 */
其实它们都是加载同样的库名,算是加载了2次,以Lua内部算法,应该只会加载一次。
更改完之后,同样需要重新编译Lua的源码,实现以上列出的关键词的中文化。
注意,在Window系统下编译Lua, 最好将所有Lua的源码,重新保存成ANSI格式的文件,刚下载的默认的源码会是UTF-8格式的。
这个事情说三遍,
1,不然就会出现,Window下的UTF-8源码可编译,但Shell里的中文输出会乱码。
2,要不然就是Window的ANSI源码不可编译(假如你没做以上步骤),
3,如果是用ANSI格式的源码编译的Lua.exe,对应的,你在Window下写的Lua程序也是需要保存成ANSI格式的。这样就可以在Shell里输出正确的中文显示。
这里就上例程演示,协程中文使用。
第一个协程 = 协程.创建(
函数(i)
输出(i,"协程.程名",协程.程名())
结束
)
协程.恢复(第一个协程, "第一个协程运作") -- 第一个协程运作 协程.程名 thread: 000001ba09d9a458 false
输出(i,"协程.状态", 协程.状态(第一个协程)) --i是传导不出来的,所以是nil, 协程.状态是(第一个协程)
输出("协程.程名是主线程么1?", 协程.程名()) -- 应该是的运行后对比 thread: 000001ba09d95ee8 true
输出("--------------第一协程分界线------------------")
程序封装的协程 = 协程.程包(
函数(i)
输出(i,"协程.程名",协程.程名()) --程序封装第一次查协程.程名 thread: 00000268b6735628 false
结束
)
程序封装的协程("程序封装第一次")
--程序封装的协程(2)
输出("第一个协程.状态", 协程.状态(第一个协程)) -- 第一个协程.状态 废弃dead
输出("协程.程名是主线程么2?", 协程.程名()) -- 应该是的运行后对比 thread: 000001ba09d95ee8 true
输出("--------------第二协程分界线------------------")
-- 创建一个能迭代打印1到10的协程,同时在迭代到3时检查自身状态和当前运行的协程。
第二个协程 = 协程.创建(
函数()
因为 i=1,10 做
输出("第二个协程第",i,"执行") -- 打印协程第二个协程的执行次数。
如果 i == 3 即
输出("协程内查1次第二个协程.状态", 协程.状态(第二个协程)) -- 打印协程第二个协程的状态,在此处第二个协程为程名
输出("有没有在第二协程内?") -- 此时还在的。
输出("第二个协程.程名", 协程.程名()) -- 打印当前正在运行的协程,为第二个协程的线程ID
输出("协程内查2次第二个协程.状态", 协程.状态(第二个协程)) -- 打印协程第二个协程的状态,在此处第二个协程为程名
输出("第二个协程.程名", 协程.程名()) -- 打印当前正在运行的协程,为第二个协程的线程ID
输出("其它协程.状态", 协程.状态()) -- 打印其它协程的状态,在此处为nil空程名,已经跳出了第二个协程,此处直接为不输出了
输出("其它协程.程名", 协程.程名()) -- 打印其它协程的程名,已经跳出了第二个协程,此处直接为不输出了
输出("第二个协程1.状态", 协程.状态(第二个协程)) -- 打印协程第二个协程的状态,因为被查其他协程状态后,已经跳出了第二个协程,此处直接为不输出了
输出("有没有在第二协程内?") --已经跳出了第二个协程,此处直接为不输出了
结束
协程.挂起() -- 暂停协程执行,让出CPU时间
结束
结束
)
-- 分三次恢复协程第二个协程的执行,使其分别打印1到3。
协程.恢复(第二个协程) --1
协程.恢复(第二个协程) --2
协程.恢复(第二个协程) --3
-- 打印协程第二个协程的状态和当前运行的协程状态。
输出("------------分界线回主线程了------------")
输出("主线程查第二个协程.状态", 协程.状态(第二个协程)) -- 挂起suspended,因为协程在 因为 循环中挂起yield了
输出("协程.程名是主程么3?", 协程.程名()) --应该是的运行后对比 thread: 000001ba09d95ee8 true
--输出("第二个协程.关闭", 协程.关闭(第二个协程)) -- 如果已经不需要第二个协程再次运作,可以关闭协程。但这会导致协程代码里,之前在第二个协程内还有四行其它协程查询出错。
输出("协程.状态是主程么4?", 协程.状态(协程.程名())) --对上与第二个协程内的协程.状态() 留空查询时不同,此时应该是主线在运行。
输出("-----结束分界线-----")
-- 以上代码展示了协程的创建、恢复执行、状态查询以及yield的使用方法。
应该能吃透协程,入门了吧,如果还不行,请关注我,后面会放出专门针对协程的更详细的说明。