如何在C# 5.0 应用程序中嵌入Lua(或其他脚本语言)

16

首先,我想提前为我的英语道歉。

我的问题是关于在C#应用程序中需要哪些内容才能解释传递给该应用程序的Lua脚本。Lua脚本必须能够访问以C#编写的类。

在搜索堆栈溢出以获取答案后,我认为处理此主题的问题已过时(我认为它们是在动态语言运行时成为.NET Framework的一部分之前提出的,而且现在拥有DLR可能更简单)。

基本上,我想做的是这样的

 TypeThatExecutesLua.MethodToLoadLuaScript(script.lua);
 TypeThatExecutesLua.Execute();

现在,假设我们不关心script.lua返回什么值。但是有些情况下第二行代码会像这样:

dynamic result = TypeThatExecutesLua.Execute();

或者这样写: dynamic result; TypeThatExecutesLua.Execute(out result);

同样地,如果可能的话,我想要能够向脚本传递参数(不确定argument是否是这种情况下的正确词语,我对脚本知之甚少),就像这样:

int argument
TypeThatExecutesLua.Execute(argument);
这可能是一个非常基础的问题,但我真的希望得到一个能够详细解释如何做到这一点的答案,而不仅仅是一个链接,因为我缺乏理解我搜索到的大部分材料的基本知识(我相当擅长C#,但这超出了语言本身的范围)。
最后,我想说的是,即使Lua是我的目标语言,如果解决方案与任何语言类似或相同,只是在项目中下载和引用哪些dll以及dll本身的接口等方面有所不同,我也想知道。

你看过NLua(http://components.xamarin.com/gettingstarted/NLua)了吗?如果看过的话,那么看了 http://lua-users.org/wiki/LuaImplementations 中.NET部分提到的其他选项了吗? - Oliver
请参阅NLuaBox - lhf
2个回答

9

看起来 DynamicLua (GitHub, NuGet 包) 有你需要的功能:

dynamic lua = new DynamicLua.DynamicLua();
lua("print('hello world')"); // => hello world
double answer = lua("return 42"); 
Console.WriteLine(answer); // => 42
var arg = 5;
lua("function luafunction(a) return a + 1 end");
dynamic answer2 = lua.luafunction(arg);
Console.WriteLine(answer2); // => 6

Console.ReadKey();

DynamicLua基于NLua,后者也可以实现所有这些功能,但会更加复杂。


0

你可以尝试使用TCL,这是嵌入式脚本的鼻祖:

(1) 下载并安装ActiveState TCL。

(2) 将文件C:\Tcl\bin\tcl86.dll和C:\Tcl\bin\zlib1.dll复制到你的C#应用程序所在的位置,很可能是在“Debug”目录下。(注意:86版本号可能需要根据你下载的TCL实际版本进行调整)你也可以将tcl86.dll复制到一个系统路径的目录中。但是,当你想要从计算机移动你的应用程序时,如果缺少tcl86.dll,这会有点令人困惑。

(3) 如果你不想让ActiveState TCL安装在C:\Tcl目录下,请删除它。

(4) 创建一个C#控制台应用程序。将项目编译属性标志设置为“不安全”代码。(因为tcl86.dll在其结果返回接口中使用char*指针。)

(5) 将以下内容剪切并粘贴到你的C#控制台项目中:

  //FILE: program.cs
  using System;

  namespace tcl1
  {
   class Program
   {
     public static void Main(string[] args)
     {
       Console.WriteLine("Hello World!");

       TclInterpreter interp = new TclInterpreter();

       //rc == 0 means OK           
       int rc = interp.evalScript("set a 3; expr {$a + 2}");
       Console.WriteLine("rc=" + rc.ToString() 
                            + " Interp.Result = " + interp.Result);

       Console.Write("Press any key to continue . . . ");
       Console.ReadKey(true);
     }//main
   } //class
 }//namespace

  //File: tcl_api.cs
  using System.Runtime.InteropServices;
  using System;

  namespace tcl1 {
    public class TclAPI {
         [DllImport("tcl86.dLL")]
         public static extern IntPtr Tcl_CreateInterp();

         [DllImport("tcl86.dll")]
         public static extern int Tcl_Eval(IntPtr interp,string skript);

         [DllImport("tcl86.dll")]
         public static extern IntPtr Tcl_GetObjResult(IntPtr interp);

         [DllImport("tcl86.dll")]
         unsafe public static extern char* 
           Tcl_GetStringFromObj(IntPtr tclObj,IntPtr length);
    }

    public class TclInterpreter {
        private IntPtr interp;

        public TclInterpreter() {
            interp = TclAPI.Tcl_CreateInterp();
            if (interp == IntPtr.Zero) {
                throw new SystemException("can not initialize Tcl interpreter");
            }
        }

        public int evalScript(string script) {
            return TclAPI.Tcl_Eval(interp,script);        
        }

        unsafe public string Result {
            get { 
                IntPtr obj = TclAPI.Tcl_GetObjResult(interp);
                if (obj == IntPtr.Zero) {
                    return "";
                } else {
                    return Marshal.PtrToStringAnsi((IntPtr)
                     TclAPI.Tcl_GetStringFromObj(obj,IntPtr.Zero));
                }
            }
        }

    }  
  }

此外,如果您需要评估TCL脚本,请在eval中使用“source”TCL命令。

也许"grandfather"这部分是关键?另外:问题是关于LUA的,回答非LUA语言可能不是人们想要点赞的东西。 - Jari Turkia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接