In order to define a method in C that is callable by Lua it has to match a given signature and use the Lua API to retrieve parameters and return results. I’m writing a C# wrapper of Lua and I’m interested in being able to call arbitrary C# methods without making them follow these conventions. When wrapping in something like D, one might use the template system to dynamically create this glue code for any given method. I was thinking this might be possible as well in C#, but by using dynamic code generation.
The C API looks something like this, and the generated code would manipulate this through a lower level part of my library which P/Invokes the Lua C library.
static int foo (lua_State *L)
{
int n = lua_gettop(L); /* number of arguments */
lua_Number sum = 0;
int i;
for (i = 1; i <= n; i++)
{
if (!lua_isnumber(L, i))
{
lua_pushstring(L, "incorrect argument");
lua_error(L);
}
sum += lua_tonumber(L, i);
}
lua_pushnumber(L, sum/n); /* first result */
lua_pushnumber(L, sum); /* second result */
return 2; /* number of results */
}
So basically the idea is to take a C# method, reflect its parameters and return values, generate (or retrieve from cache) a method that uses the Lua API like above to pass those parameters and return those return types and finally push that method to Lua. So when C# function is called from Lua it looks something like lua -> magic wrapper function -> ordinary C# function.
Thanks.
If I understand what you want, it seems you have 2 options:
CodeDom is sort of hairy, very low-level code to write. The idea is there’s an object model for the C# language. You start by instantiating a CodeTypeDeclaration – this will generate a type or class. Then you add properties and fields – here you would likely add
DllImportdeclarations for your p/invoke functions. Then you use different CodeDOM add methods to the type – this would be where you’d insert the generated method. You could make it public, static, whatever you like.CodeDOM looks like this:
it goes on. and on. As you can see, it gets pretty ugly. Then later you compile it, which I did not show. I’m assuming you’re not gonna want to take this approach.
I found CodeDom to be pretty crufty to use; instead, now when I need dynamically-generated assemblies, I will emit actual C# code, normally via templates, into a string in memory, and compile that. It’s much simpler for my purposes. The compilation looks like this:
In the above code,
LiteralSourcecontains the source code to be compiled. As I said, I generate this by reading a template and filling in the blanks.