Search code examples
c#luanlua

How to use C# static string with Nlua


I am using NLua for script interface with my application. I want to send keyboard input from LUA language to my C# code.

I do with this C# code.

   using (Lua lua = new Lua())
   {
      lua.LoadCLRPackage();

      lua.RegisterFunction("keypressC", null, typeof(TestNLUA).GetMethod("keypressC"));
      lua.RegisterFunction("keypressS", null, typeof(TestNLUA).GetMethod("keypressS"));

      lua["Key"] = new SpecialKey();
   }

    public class SpecialKey
    {
        public static readonly char EnterC = '\uE007'; 
        public static readonly string EnterS = Convert.ToString(EnterC);
    }

   public class TestNLUA
   {
      public static void keypressC(char key)
      {
         // key = 57351 => OK
      }

      public static void keypressS(string key)
      {
         char[] akey = key.ToCharArray();
         // akey[0] = 63 = ? (question mark) => KO
      }
   }

And in LUA Script I do

keypressC(Key.EnterC)
keypressS(Key.EnterS)

In keypressC, Nlua passe value 57351 to key parameter. It's OK.

In keypressS, Nlua passe value "?" to key parameter. It's KO. I have no idea why there is the character "?". Looks like a marshaling error in NLua (i.e. LuaInterface)?

Can you help me?


Solution

  • This is a marshaling problem in nLua/LuaInterface.

    It uses Marshal.StringToHGlobalAnsi to marshal a string from C# to Lua.
    It uses Marshal.PtrToStringAnsi to marshal a string from Lua to C#.

    If you round-trip your example string through these functions, you can see it reproduces your problem:

     string test = "\uE007";
    
     Console.WriteLine(test);
     Console.WriteLine("{0}: {1}", test[0], (int) test[0]);
    
     IntPtr ptr = Marshal.StringToHGlobalAnsi(test);
     string roundTripped = Marshal.PtrToStringAnsi(ptr, test.Length);
    
     Console.WriteLine(roundTripped);
     Console.WriteLine("{0}: {1}", roundTripped[0], (int) roundTripped[0]);
    

    Output:

    ?
    ?: 57351
    ?
    ?: 63
    

    Your problem goes away if you change the the marshaling functions to use Uni instead of Ansi, but you'd need to build nLua/LuaInterface from source.