1

I have a DLL written in C# that is used by Lua scripts. The scripts "require CLRPackage". So far I can load_assembly() and import_type() to get at the classes and methods in my DLL. I'm passing back simple values and strings, and that all works.

No I need to pass a generic collection back to Lua. I believe that what Lua will see is a table, but it isn't clear to me how to create that table in C# and pass it back.

This seems to be a similar question, but I'm not seeing how to implement it. Is there another solution or one with a stripped down code fragment?

Community
  • 1
  • 1
halm
  • 104
  • 3
  • 10

1 Answers1

5

Now I need to pass a generic collection back to Lua. I believe that what Lua will see is a table

It won't. Lua will see a CLR object (rather, a userdata proxy for the CLR object).

If you had a method in your C# class like this:

public List<string> GetList()
{
    return new List<string> { "This", "bar", "is", "a" };
}

The Lua side (after you loaded the module, grabbed the class and instantiated it as, say, foo):

local list = foo:GetList()
print(list)

That will give you something like System.Collections.Generic.List1[System.String]: 33476626. This is a userdata, not a table, so you can't use next or pairs to iterate through it, you have to interact with it as it were a C# List<string>:

local it = list:GetEnumerator()
while it:MoveNext() do
  print(it.Current)
end

This is very ugly, non-idiomatic Lua to be sure (even non-idiomatic C#, given that you'd use foreach in C#), but I don't think there's any automatic marshalling between LuaInterface types and CLR types. Kinda hard to tell; LuaInterface documentation is almost nonexistent.

You could write your own routines to marshal between Lua and CLR types, like:

function listToTable(clrlist)
    local t = {}
    local it = clrlist:GetEnumerator()
    while it:MoveNext() do
      t[#t+1] = it.Current
    end
    return t
end
    
...
    
local list = listToTable(foo:GetList())
for key, val in pairs(list) do
  print(key,val)
end

Add a dictToTable and you'd be pretty much covered.

Mud
  • 28,277
  • 11
  • 59
  • 92
  • Thanks so much. I'm pretty new to both C# and Lua, and that's very helpful. I'm home right now but will experiment with this when I get back to work. I've been thinking that an alternative might be to provide my own iterator. My C# would expose a GetNumberOfItems() and a GetNextItem(), or perhaps a GetItem(int index), and then my Lua could loop to retrieve items at will. This solution seems a little bit less ugly than what I was contemplating. What do you think? – halm Jun 09 '12 at 05:53
  • Hey Mud, any idea how to get the list size in lua? – pragnesh Jul 07 '15 at 11:44
  • The userdata is a proxy for the C# object, so it's should have its interface. In other words, [list:Count](https://msdn.microsoft.com/en-us/library/5s3kzhec%28v=vs.110%29.aspx) should do the trick. – Mud Jul 07 '15 at 18:28