• Lua中文语言编程源码-第五节,更改lcorolib.c协程库函数, 使Lua加载中文库关键词(与所有的基础库相关)


    源码已经更新在CSDN的码库里:

    git clone https://gitcode.com/funsion/CLua.git

    在src文件夹下的lcorolib.c协程库函数,Coroutine Library:表明这个C源文件实现了Lua的协程库(Coroutine Library),即提供了与协程相关的API和功能实现。

    增加中文版协程函数名列表,保留英文版协程函数名列表。

    原始的代码为:
    1. static const luaL_Reg co_funcs[] = {
    2. {"create", luaB_cocreate},
    3. {"resume", luaB_coresume},
    4. {"running", luaB_corunning},
    5. {"status", luaB_costatus},
    6. {"wrap", luaB_cowrap},
    7. {"yield", luaB_yield},
    8. {"isyieldable", luaB_yieldable},
    9. {"close", luaB_close},
    10. {NULL, NULL}
    11. };
     更改成以下代码:
    1. /*
    2. * 协程功能的注册表
    3. * 该表包含了所有协程相关函数的英文名和中文名,以及它们对应的实现函数。
    4. * 该注册表用于在Lua中注册这些协程函数,以便于在Lua脚本中调用。
    5. */
    6. static const luaL_Reg co_funcs[] = {
    7. /* 英文版协程函数名 */
    8. {"create", luaB_cocreate}, /* 创建一个新的协程 */
    9. {"resume", luaB_coresume}, /* 恢复一个协程的执行 */
    10. {"running", luaB_corunning}, /* 获取当前正在运行的协程 */
    11. {"status", luaB_costatus}, /* 获取一个协程的状态 */
    12. {"wrap", luaB_cowrap}, /* 将一个函数封装成一个协程 */
    13. {"yield", luaB_yield}, /* 使当前协程挂起 */
    14. {"isyieldable", luaB_yieldable}, /* 检查当前协程是否可以挂起 */
    15. {"close", luaB_close}, /* 关闭一个协程 */
    16. /* 中文版协程函数名 */
    17. {"创建", luaB_cocreate}, /* 创建一个新的协程 */
    18. {"恢复", luaB_coresume}, /* 恢复一个协程的执行 */
    19. {"程名", luaB_corunning}, /* 获取当前正在运行的协程 */
    20. {"状态", luaB_costatus}, /* 获取一个协程的状态 */
    21. {"程包", luaB_cowrap}, /* 将一个函数封装成一个协程 */
    22. {"挂起", luaB_yield}, /* 使当前协程挂起 */
    23. {"可挂起", luaB_yieldable}, /* 检查当前协程是否可以挂起 */
    24. {"关闭", luaB_close}, /* 关闭一个协程 */
    25. {NULL, NULL} /* 注册表结束标志 */
    26. };

    为了保证中英文协程函数都可以加载,以便你可以复制英文原码来进行更改。所以保留了英文版协程函数名列表,这样就能使用两种文的函数。

    {"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里输出正确的中文显示。

    这里就上例程演示,协程中文使用。

    1. 第一个协程 = 协程.创建(
    2. 函数(i)
    3. 输出(i,"协程.程名",协程.程名())
    4. 结束
    5. )
    6. 协程.恢复(第一个协程, "第一个协程运作") -- 第一个协程运作 协程.程名 thread: 000001ba09d9a458 false
    7. 输出(i,"协程.状态", 协程.状态(第一个协程)) --i是传导不出来的,所以是nil, 协程.状态是(第一个协程)
    8. 输出("协程.程名是主线程么1?", 协程.程名()) -- 应该是的运行后对比 thread: 000001ba09d95ee8 true
    9. 输出("--------------第一协程分界线------------------")
    10. 程序封装的协程 = 协程.程包(
    11. 函数(i)
    12. 输出(i,"协程.程名",协程.程名()) --程序封装第一次查协程.程名 thread: 00000268b6735628 false
    13. 结束
    14. )
    15. 程序封装的协程("程序封装第一次")
    16. --程序封装的协程(2)
    17. 输出("第一个协程.状态", 协程.状态(第一个协程)) -- 第一个协程.状态 废弃dead
    18. 输出("协程.程名是主线程么2?", 协程.程名()) -- 应该是的运行后对比 thread: 000001ba09d95ee8 true
    19. 输出("--------------第二协程分界线------------------")
    20. -- 创建一个能迭代打印110的协程,同时在迭代到3时检查自身状态和当前运行的协程。
    21. 第二个协程 = 协程.创建(
    22. 函数()
    23. 因为 i=1,10
    24. 输出("第二个协程第",i,"执行") -- 打印协程第二个协程的执行次数。
    25. 如果 i == 3
    26. 输出("协程内查1次第二个协程.状态", 协程.状态(第二个协程)) -- 打印协程第二个协程的状态,在此处第二个协程为程名
    27. 输出("有没有在第二协程内?") -- 此时还在的。
    28. 输出("第二个协程.程名", 协程.程名()) -- 打印当前正在运行的协程,为第二个协程的线程ID
    29. 输出("协程内查2次第二个协程.状态", 协程.状态(第二个协程)) -- 打印协程第二个协程的状态,在此处第二个协程为程名
    30. 输出("第二个协程.程名", 协程.程名()) -- 打印当前正在运行的协程,为第二个协程的线程ID
    31. 输出("其它协程.状态", 协程.状态()) -- 打印其它协程的状态,在此处为nil空程名,已经跳出了第二个协程,此处直接为不输出了
    32. 输出("其它协程.程名", 协程.程名()) -- 打印其它协程的程名,已经跳出了第二个协程,此处直接为不输出了
    33. 输出("第二个协程1.状态", 协程.状态(第二个协程)) -- 打印协程第二个协程的状态,因为被查其他协程状态后,已经跳出了第二个协程,此处直接为不输出了
    34. 输出("有没有在第二协程内?") --已经跳出了第二个协程,此处直接为不输出了
    35. 结束
    36. 协程.挂起() -- 暂停协程执行,让出CPU时间
    37. 结束
    38. 结束
    39. )
    40. -- 分三次恢复协程第二个协程的执行,使其分别打印13
    41. 协程.恢复(第二个协程) --1
    42. 协程.恢复(第二个协程) --2
    43. 协程.恢复(第二个协程) --3
    44. -- 打印协程第二个协程的状态和当前运行的协程状态。
    45. 输出("------------分界线回主线程了------------")
    46. 输出("主线程查第二个协程.状态", 协程.状态(第二个协程)) -- 挂起suspended,因为协程在 因为 循环中挂起yield了
    47. 输出("协程.程名是主程么3?", 协程.程名()) --应该是的运行后对比 thread: 000001ba09d95ee8 true
    48. --输出("第二个协程.关闭", 协程.关闭(第二个协程)) -- 如果已经不需要第二个协程再次运作,可以关闭协程。但这会导致协程代码里,之前在第二个协程内还有四行其它协程查询出错。
    49. 输出("协程.状态是主程么4?", 协程.状态(协程.程名())) --对上与第二个协程内的协程.状态() 留空查询时不同,此时应该是主线在运行。
    50. 输出("-----结束分界线-----")
    51. -- 以上代码展示了协程的创建、恢复执行、状态查询以及yield的使用方法。

    应该能吃透协程,入门了吧,如果还不行,请关注我,后面会放出专门针对协程的更详细的说明。

  • 相关阅读:
    VS c++多文件编译
    LeetCode_730_每日温度
    【数组】大数加法(正整数)
    MySQL多表
    IC设计中glitch free时钟选择器的设计过程
    Ubuntu 22.04 配置VirtualBox安装Windows 10虚拟机
    Clickhouse的基本sql语句
    代码整洁之道
    Vue 3 的 setup语法糖到底是什么东西?
    部署云 SIEM 解决方案的 5 大优势
  • 原文地址:https://blog.csdn.net/funsion/article/details/136748538