当前位置: 首页 > news >正文

MoonSharp 文档五

目录

13.Coroutines(协程)

Lua中的协程

从CLR代码中的协程

从CLR代码中的协程作为CLR迭代器

注意事项

抢占式协程

14.Hardwire descriptors(硬编码描述符)

为什么需要“硬编码”

什么是“硬编码”

如何进行硬编码

硬编码的优缺点

硬编码是实现IL2CPP、AOT或iOS兼容性的必要条件吗?

术语表

15.Sandboxing(沙盒)

为什么需要沙盒化

沙盒化检查清单

移除“危险”的 API

16.Tips and tricks for Unity3D(Unity3D的提示和技巧)

支持的平台

其他建议

使用更显式的构造函数之一初始化脚本加载器

17.FAQ / Recipes

如何重定向打印函数的输出?

如何将输入重定向到Lua程序?

如何重定向Lua程序的IO流?

如何限制脚本在不丢失状态的情况下执行的指令数?


MoonSharp 文档一-CSDN博客

MoonSharp 文档二-CSDN博客

MoonSharp 文档三-CSDN博客

MoonSharp 文档四-CSDN博客

13.Coroutines(协程)

来自 C# 和 Lua。

文档地址:MoonSharp

Lua中的协程

Lua 中的协程是开箱即用的支持。实际上,只要你不故意排除协程模块(参见沙盒化),它们就可以免费使用。有很多注意事项(这些也偶然适用于原始的 Lua 实现),并在下面的 “注意事项” 部分进行了讨论。

使用任何 Lua 协程教程来操作它们。

从CLR代码中的协程

协程可以通过脚本 CreateCoroutine 方法创建,该方法接受一个必须是函数的 DynValue。

string code = @"
	return function()
		local x = 0
		while true do
			x = x + 1
			coroutine.yield(x)
		end
	end
	";

// Load the code and get the returned function
Script script = new Script();
DynValue function = script.DoString(code);

// Create the coroutine in C#
DynValue coroutine = script.CreateCoroutine(function);

// Resume the coroutine forever and ever..
while (true)
{
	DynValue x = coroutine.Coroutine.Resume();
	Console.WriteLine("{0}", x);
}

从CLR代码中的协程作为CLR迭代器

可以像调用迭代器一样调用协程:

string code = @"
	return function()
		local x = 0
		while true do
			x = x + 1
			coroutine.yield(x)
			if (x > 5) then
				return 7
			end
		end
	end
	";

// Load the code and get the returned function
Script script = new Script();
DynValue function = script.DoString(code);

// Create the coroutine in C#
DynValue coroutine = script.CreateCoroutine(function);

// Loop the coroutine 
string ret = "";

foreach (DynValue x in coroutine.Coroutine.AsTypedEnumerable())
{
	ret = ret + x.ToString();
}

Assert.AreEqual("1234567", ret);

注意事项

现在我们来到了协程相关内容中最重要的部分。就像在原始的 Lua 中一样,无法从嵌套调用中执行 yield 操作。

特别是在 MoonSharp 中,如果你在从 Lua 调用的 C# 函数中调用一个脚本,你不能使用 yield 来恢复到 C# 调用外部的协程。

不过有一个解决办法:返回一个 TailCallRequest 类型的 DynValue

return DynValue.NewTailCallReq(luafunction, arg1, arg2...); 

还可以指定一个 continuation(延续)——这是一段函数,它将在尾调用执行完成后被调用。

在 99% 的情况下,这可能是过度设计——甚至在大多数情况下,Lua 标准库也无法正确处理回调与 yield 的结合。但如果你计划自己实现像 `load`、`pcall` 或 `coroutine.resume` 这样的 API,这就是必需的。

另外,在某些边缘情况下,MoonSharp 处理 yield 的方式与标准 Lua 不同(在我尝试过的所有情况中,MoonSharp 的方式都更好,但谁知道呢)。例如,`tostring()` 支持在调用 `__tostring` 元方法时执行 yield 操作,而不会引发错误。

抢占式协程

在 MoonSharp 中,即使协程没有调用 `coroutine.yield`,也可以将其挂起。例如,如果想要非破坏性地限制脚本占用的 CPU 时间,这可能会很有用。但为了保持脚本的一致性,有一些需要注意的地方。

让我们从一个例子开始:

string code = @"
	function fib(n)
		if (n == 0 or n == 1) then
			return 1;
		else
			return fib(n - 1) + fib(n - 2);
		end
	end
	";

// Load the code and get the returned function
Script script = new Script(CoreModules.None);
script.DoString(code);

// get the function
DynValue function = script.Globals.Get("fib");

// Create the coroutine in C#
DynValue coroutine = script.CreateCoroutine(function);

// Set the automatic yield counter every 10 instructions. 
// 10 is likely too small! Use a much bigger value in your code to avoid interrupting too often!
coroutine.Coroutine.AutoYieldCounter = 10;

int cycles = 0;
DynValue result = null;

// Cycle until we get that the coroutine has returned something useful and not an automatic yield..
for (result = coroutine.Coroutine.Resume(8); 
	result.Type == DataType.YieldRequest;
	result = coroutine.Coroutine.Resume()) 
{
	cycles += 1;
}

// Check the values of the operation
Assert.AreEqual(DataType.Number, result.Type);
Assert.AreEqual(34, result.Number);

步骤如下:

1. 创建一个协程 

2. 将 `AutoYieldCounter` 设置为一个大于 0 的数字。1000 是一个不错的起点,可以根据需要调整。这个数字表示在执行多少条指令后,协程会主动挂起并返回给调用者。  

3. 调用 `coroutine.Coroutine.Resume(...)` 并传入适当的参数。

4. 如果上述调用的返回类型是 `DataType.YieldRequest`,则不带参数调用 `coroutine.Coroutine.Resume()`。 

5. 重复上一步,直到返回一个真正的结果类型。 

6. 完成。  

注意事项:

1. 如果代码重新进入(例如,`string.gsub` 的回调函数&#

相关文章:

  • 练习:关于静态路由,手工汇总,路由黑洞,缺省路由相关
  • 语音视频App协议安全实战:防御伪造/窃听/Deepfake攻击
  • 深度学习分词器char-level实战详解
  • 循环队列概念和结构
  • 决策树的核心思想
  • c语言笔记 函数参数的等价(下)
  • 华为eNSP:2.配置OSPF报文分析和验证
  • Redis 发布订阅模式详解:实现高效的消息通信
  • Redis未授权访问
  • AI-NAS:当存储遇上智能,开启数据管理新纪元
  • 【工控】线扫相机小结 第五篇
  • 开源模型时代的 AI 开发革命:Dify 技术深度解析
  • SpringMVC项目中,涉及到的各种请求
  • 店匠科技携手 PayPal 升级支付体验,助力独立站商家实现全球增长
  • 重邮数字信号处理-实验五时域采样与频域采样
  • 数据结构(蓝桥杯常考点)
  • 我的AI工具箱Tauri版-建筑平面图生成装修设计
  • Flutter:StatelessWidget vs StatefulWidget 深度解析
  • 如何修复“RPC 服务器不可用”错误
  • 第三章 数据结构基础
  • 特朗普与普京开始电话会谈,稍后将致电泽连斯基
  • 国家统计局:下阶段要继续发挥宏观政策作用,促进价格合理回升
  • 一个留美学生的思想转向——裘毓麐的《游美闻见录》及其他
  • 篮球培训机构东方启明星被指停摆,家长称已登记未退费用超百万
  • 遭车祸罹难的村医遇“身份”难题:镇卫生院否认劳动关系,家属上诉后二审将开庭
  • 巴菲特最新调仓:一季度大幅抛售银行股,再现保密仓位