-
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.
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. Generic method calls are handled by returning another function if the original attempt to call the method fails! In particular, the following declaration can be problematic:
void Method<T>();
void Method(Type t);
The second method will always be called with the Method(type)
syntax, making it impossible to call the first method whatsoever. This can theoretically be resolved by using reflection from within Lua, but this edge case is rare enough in the first place.
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");