-
Notifications
You must be signed in to change notification settings - Fork 1
.NET Bindings
Bindings to .NET objects are achieved using userdata with metamethods that emulate typical C# access of the .NET object. Objects are stored using strong GCHandle
s, preventing the .NET GC from garbage collecting them. This approach obviates the need of assigning each object a unique ID and performing a lookup for every access.
All bindings are wrapped in a function which reports errors using the error
function instead of P/Invoking the luaL_error
function! The issue with P/Invoking luaL_error
is that this calls longjmp
, which can have undefined results on the stack.
The members of a .NET object or static members of a .NET type are accessed using the __index
metamethod. In particular, methods will return a function which can be called at a later time, events will return a wrapper object that handles event subscription and unsubscription, and indexed properties will return a wrapper object that handles getting and setting. These special results are cached to improve performance.
One-dimensional arrays are also accessed in the same manner. Multi-dimensional arrays must be accessed using the GetValue
function.
Method calls will ignore out
parameters for the purpose of input validation, and will return ref
and out
parameters as extra return values. Triton's overload resolution will always handle the following case correctly by picking the method with the least number of default values applied:
void Method(int a);
void Method(int a, int b = 0);
Generic method calls are handled in the failure condition of a normal method call. Another function will be returned, treating the original arguments as type arguments. However, this method of supporting generic methods leads to the following problem:
void Method<T>();
void Method(Type t);
The first method can never be called, because a single type argument is valid for the second method. However, this edge case is rare, and can be resolved by using reflection from within Lua.
The members of a .NET object or static members of a .NET type are modified using the __newindex
metamethod.
One-dimensional arrays are also modified in the same manner. Multi-dimensional arrays must be modified using the SetValue
function.
If a .NET object is a Delegate
, then it can be called using the __call
metamethod. A .NET type can also be instantiated using the __call
metamethod, and if it is a generic type, then it will return a constructed generic type which can then be instantiated.
The operators of a .NET object are implemented using the various operator metamethods. In particular, both operands of a binary operation will be checked for an operator that satisfies the given signature! This deals with the following edge case:
public class Test1 {
public static int operator +(Test2 t2, Test1 t1);
}
public class Test2 {
public static int operator +(Test2 t2, int i);
}
lua["t1"] = new Test1();
lua["t2"] = new Test2();
lua.DoString("x = t2 + t1");