我可以在 Nlua 中使用静态类吗?

问题描述

首先,我的母语不是英语,对于这个问题可能会出现的任何沟通错误,我深表歉意。另外,无法真正理解您提出问题的一些准则,因此请按照我的理解进行操作。因此,如果我违反了任何习俗,请告诉我。

背景

我一直在制作一个应用程序,试图为代码实现类似 xaml 热重载的功能。由于我不能直接用像 c# 这样的编译语言来实现它,我决定依赖第三方脚本语言,认为我可以在其中编写一些我的应用程序逻辑,然后将它更快地部署到设备上,因为我会只需按一个按钮即可发送代码。所以,可以把它想象成 react-native 世界中的 expo 客户端。

我决定使用 lua 作为脚本语言,不仅因为它编写代码非常简单,还因为它对 .net 有很好的绑定,当然我说的是 Nlua。而且,由于 Ironpython3 还没有准备好投入生产,老实说我有什么选择?

我面临的问题

因此,由于我必须绑定一些 xamarin.essentials 内容以使我更轻松地编写应用程序的 lua 端,因此我必须与一些对象进行交互,这些对象具有静态方法等。我认为在 Nlua 中使用静态方法会非常直观和直接,尽管到目前为止我似乎错了。

如何重现问题

  1. 因此,在 Visual Studio 中,创建一个 xamarin.forms 项目,随意命名,这无关紧要。
  2. 接下来,将 Nlua nuget 包添加到您的所有项目中。它需要集成到所有这些中,因为它与一些 xamarin.forms 插件一样,依赖本机库才能工作,因此需要将它们包含在适当的位置,以便操作系统找到它们。当安装在受支持的项目类型中时,包会自动完成此操作,因此请执行此操作。
  3. 将 Nlua 命名空间添加到 MainPage 内容页面的代码隐藏顶部,如下所示:
    using NLua;  
  1. 为了方便以后的使用,向 MainPage 类添加一个类级别的属性,如下所示:
    Lua LuaState{get; set;}  
  1. 现在,为了简单起见,在页面构造函数中初始化它:
    LuaState = new Lua();
  1. 页面的 xaml 中,添加一个用于输入文本的编辑字段和一个能够运行它的按钮:
    <StackLayout>
        
        <Editor
                x:Name="edCode"
            Placeholder="type your code here"    
            />

            <Button
                x:Name="btnStartCode"
                Text="compile"
                HorizontalOptions="End"
                VerticalOptions="EndAndExpand"
                Clicked="btnStartCode_Clicked"
            />
    </StackLayout>
  1. 在按钮单击处理程序中,添加代码以加载编辑框中的内容,然后让 nlua 执行它,如下所示:
    async void btnStartCode_Clicked(object sender,EventArgs e)
    {
        try
        {
            LuaState.DoString(edCode.Text);
        }
        catch (Exception exc)
        {
            await displayAlert("error",$"A Fatal error was incountered while running your code\nException details:\n\tException type: {exc.GetType().ToString()}\n\terror message from interpreter:{exc.Message}.","OK");
        }

    }
  1. 现在,添加一个新类,随意调用它,我称之为 tts。删除vs生成文件里面的所有内容,然后在里面添加以下内容
    using System;
    
        using System.Collections.Generic;
        using System.Text;
        using Xamarin.Essentials;
        namespace autoaccess.scriptables
        {
            public class tts
            {
                public async void speak(params object[] messages)
                {
                    foreach(var message in messages)
                    {
                        if (message == null)
                        {
                            await TextToSpeech.SpeakAsync("null value");
                            return;
                        }
                        await TextToSpeech.SpeakAsync(message.ToString());
                    }
                }
            }
        }
  1. 回到主要内容类,在构造函数或从构造函数调用的专用方法中,注册lua类型,如下所示:
LuaState["text_to_speech"=typeof(TextToSpeech);  

预期行为

如果使用 . 表示法,它应该说出给函数的参数,例如 tts.speak("hello world")

实际行为

执行带有 . 符号的调用时,lua 解释器抛出以下错误

[string "chunk"]:1: 尝试调用一个 nil 值(字段 'speak')。

到目前为止我尝试了什么

  1. 首先,我尝试使用 typeof 关键字获取静态对象的类型,然后将其直接注册为 lua 可访问值,如上所示。如您所见,这引发了一个错误
  2. 例如,如果我尝试像函数一样调用类型来获取文档中所示的新对象,它会再次失败。
  3. 如果我使用 State.UseClrPackage(); 方法,然后手动导入内容,它也不起作用,无法访问任何方法或变量,lua 说它们都是“nill”。立>

注意:仔细检查后,我看到变量 lua 看到的实际上是真正的 clr 类型,因为 lua 的 str 函数显示了完整的类型限定符,如 .net 中所示。然而,类型函数返回用户数据。

  1. 我没有让整个类型对 lua 可见,而是尝试用名称创建一个 lua 表,然后添加键值对,其中键是方法名称,值是静态对象的方法,由 typeof(thing).getmethod(MethodName) 转换为 LuaFunction 类型返回。 这在一定程度上奏效了,尽管它很快让我觉得太复杂和难以承受,所以我停止使用这种方法,因为我的代码库很混乱。

  2. 我尝试的另一件事是为静态对象创建代理对象,其中实际上没有任何东西是静态的,即使这些方法返回 void 并作用于静态属性

这又一次奏效了,但是我必须使用 object:thing,而静态方法的规范是 object.thing。如果我尝试使用 object.thing 表示法,我会得到一个相当长的错误,尽管我确定它的内容与手头的问题无关,所以不打算在这里包含它。

结论

所以,正式地,我尝试了我所能做的一切,甚至在这里进行了搜索,看看我是否能够找到任何可以启发我的东西,尽管不幸的是没有运气。现在,您建议我使用什么?有什么我忽略的地方吗?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)