How to embed lua (or some other scripting language) in a C# 5.0 application
Asked Answered
P

2

16

First of all, I'd like to appoligize in advance for my English.

My question is specifically about what do I need to have in a C# application to be able to interpret a Lua script fed to said application. The Lua scripts must be able to have access to classes written in C#.

After searching stack overflow for an answer, I think the questions that deal with this subject are outdated (I think they were asked before the Dynamic Language Runtime became a part of the .NET Framework, and I think things mat be simpler now that we have the DLR).

Basically, what I wanted to do is this

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

Now, that's supposing we don't care what script.lua returns. But there would be scenarios where the second line would be something like this:

dynamic result = TypeThatExecutesLua.Execute();

or this: dynamic result; TypeThatExecutesLua.Execute(out result);

Similarly, if possible, I'd like to be able to pass arguments to the scripts (not sure if argument is the right word in this case, I know little about scripts), like this:

int argument
TypeThatExecutesLua.Execute(argument);

This is probably a very basic question, but I'd really appreciate an answer that would really explain to me how to do this, instead of a link to some page, because I lack the basic knowledge to understand most of the material I came across so far by searching the web (I'm fairly good at C#, but this is out of the scope of the language itself).

As a final note, I'd like to say that even though Lua is my target language, if the solution is similar or identical to any language, varying only in things like which dll to download and reference in your project and the interface of dll itself, I'd like to know.

Ploss answered 8/3, 2014 at 9:51 Comment(2)
Have you look at NLua (components.xamarin.com/gettingstarted/NLua)? If so, at any of the other options mentioned in the .NET section of lua-users.org/wiki/LuaImplementations?Loafer
See also NLuaBox.Ironsmith
K
10

It looks like DynamicLua (GitHub, NuGet Package) has what you want:

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 is based on NLua, which can do all of this as well, but it will be more complicated.

Kosak answered 8/3, 2014 at 18:40 Comment(0)
P
0

You could try using TCL, the grandfather of embedded scripting:

(1) Download ActiveState TCL and install.

(2) Copy File C:\Tcl\bin\tcl86.dll and C:\Tcl\bin\zlib1.dll to the place where your C# exe is located for your application, most likely under "Debug" directory. (Note:86 version number may need to be adjusted to the actual version of TCL that you downloaded) You can also copy the tcl86.dll to a directory that is your SYSTEM path. However, that is a bit confusing when you want to move your application from your computer and it doesn't work because a tcl86.dll is missing.

(3) Delete ActiveState TCL install if you don't want it under C:\Tcl directory.

(3) Create a C# console application. Set the project compile properties flag to "unsafe" code. (because tcl86.dll makes use of a char* pointer in its result return interface.)

(4) cut and paste the following into your c# console project:

  //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));
                }
            }
        }

    }  
  }

Also, If you need to evaluate a TCL script, use the "source" TCL command in the eval.

Perpetrate answered 9/3, 2017 at 15:28 Comment(1)
Maybe the "grandfather"-part is the key here? Also: question was about LUA, answering for a non-LUA language may not be the thing people would like to upvote.Almund

© 2022 - 2024 — McMap. All rights reserved.