"packages/KeraLua.1.0.22/lib/MonoAndroid/KeraLua.xml" did not exist on "008c44e2f4e1fcf06a864e3f300d7af0e6c81259"
Commit 27e4f04c authored by Vinicius Jarina's avatar Vinicius Jarina
Browse files

Fixed call delegate functions.

Automatically register metamethod __call for delegate types.
+ Unit tests.
parent d7f1849b
...@@ -10,14 +10,17 @@ using NLuaTest; ...@@ -10,14 +10,17 @@ using NLuaTest;
namespace ConsoleTest namespace ConsoleTest
{ {
public class Program public class Program
{ {
static void Main (string [] args) static void Main (string [] args)
{ {
Core c = new Core (); using (var l = new Lua ()) {
c.Setup (); Action c = () => { Console.WriteLine ("Ola"); };
c.Sieve (); l ["d"] = c;
l.DoString (" d () ");
}
} }
} }
} }
...@@ -61,6 +61,7 @@ namespace NLua ...@@ -61,6 +61,7 @@ namespace NLua
public LuaNativeFunction ExecuteDelegateFunction { get; private set; } public LuaNativeFunction ExecuteDelegateFunction { get; private set; }
public LuaNativeFunction CallConstructorFunction { get; private set; } public LuaNativeFunction CallConstructorFunction { get; private set; }
public LuaNativeFunction ToStringFunction { get; private set; } public LuaNativeFunction ToStringFunction { get; private set; }
public LuaNativeFunction CallDelegateFunction { get; private set; }
public LuaNativeFunction AddFunction { get; private set; } public LuaNativeFunction AddFunction { get; private set; }
public LuaNativeFunction SubtractFunction { get; private set; } public LuaNativeFunction SubtractFunction { get; private set; }
...@@ -109,6 +110,7 @@ namespace NLua ...@@ -109,6 +110,7 @@ namespace NLua
ClassIndexFunction = new LuaNativeFunction (MetaFunctions.GetClassMethod); ClassIndexFunction = new LuaNativeFunction (MetaFunctions.GetClassMethod);
ClassNewindexFunction = new LuaNativeFunction (MetaFunctions.SetClassFieldOrProperty); ClassNewindexFunction = new LuaNativeFunction (MetaFunctions.SetClassFieldOrProperty);
ExecuteDelegateFunction = new LuaNativeFunction (MetaFunctions.RunFunctionDelegate); ExecuteDelegateFunction = new LuaNativeFunction (MetaFunctions.RunFunctionDelegate);
CallDelegateFunction = new LuaNativeFunction (MetaFunctions.CallDelegate);
AddFunction = new LuaNativeFunction (MetaFunctions.AddLua); AddFunction = new LuaNativeFunction (MetaFunctions.AddLua);
SubtractFunction = new LuaNativeFunction (MetaFunctions.SubtractLua); SubtractFunction = new LuaNativeFunction (MetaFunctions.SubtractLua);
MultiplyFunction = new LuaNativeFunction (MetaFunctions.MultiplyLua); MultiplyFunction = new LuaNativeFunction (MetaFunctions.MultiplyLua);
...@@ -605,7 +607,16 @@ namespace NLua ...@@ -605,7 +607,16 @@ namespace NLua
SetMemberCache (memberCache, objType, methodName, member); SetMemberCache (memberCache, objType, methodName, member);
try { try {
translator.Push (luaState, field.GetValue (obj)); var value = field.GetValue (obj);
if (!(value is Delegate)) {
translator.Push (luaState, value);
} else {
Delegate del = (Delegate)value;
var wrapper = new LuaNativeFunction ((new LuaMethodWrapper (translator, del.Target, objType, del.Method)).invokeFunction);
translator.PushFunction (luaState, wrapper);
translator.Push (luaState, true);
return 2;
}
} catch { } catch {
LuaLib.LuaPushNil (luaState); LuaLib.LuaPushNil (luaState);
} }
...@@ -619,8 +630,16 @@ namespace NLua ...@@ -619,8 +630,16 @@ namespace NLua
SetMemberCache (memberCache, objType, methodName, member); SetMemberCache (memberCache, objType, methodName, member);
try { try {
object val = property.GetValue (obj, null); object value = property.GetValue (obj, null);
translator.Push (luaState, val); if (!(value is Delegate)) {
translator.Push (luaState, value);
} else {
Delegate del = (Delegate)value;
var wrapper = new LuaNativeFunction ((new LuaMethodWrapper (translator, del.Target, objType, del.Method)).invokeFunction);
translator.PushFunction (luaState, wrapper);
translator.Push (luaState, true);
return 2;
}
} catch (ArgumentException) { } catch (ArgumentException) {
// If we can't find the getter in our class, recurse up to the base class and see // If we can't find the getter in our class, recurse up to the base class and see
// if they can help. // if they can help.
...@@ -1006,6 +1025,53 @@ namespace NLua ...@@ -1006,6 +1025,53 @@ namespace NLua
return SetMember (luaState, target, null, BindingFlags.Static); return SetMember (luaState, target, null, BindingFlags.Static);
} }
/*
* __call metafunction of Delegates.
*/
#if MONOTOUCH
[MonoTouch.MonoPInvokeCallback (typeof (LuaNativeFunction))]
#endif
static int CallDelegate (LuaState luaState)
{
var translator = ObjectTranslatorPool.Instance.Find (luaState);
var instance = translator.MetaFunctionsInstance;
return instance.CallDelegateInternal (luaState);
}
int CallDelegateInternal (LuaState luaState)
{
object objDelegate = translator.GetRawNetObject (luaState, 1);
if (objDelegate == null || !(objDelegate is Delegate)) {
translator.ThrowError (luaState, "trying to invoke a not delegate or callable value");
LuaLib.LuaPushNil (luaState);
return 1;
}
LuaLib.LuaRemove (luaState, 1);
var validDelegate = new MethodCache ();
Delegate del = (Delegate)objDelegate;
MethodBase methodDelegate = del.Method;
bool isOk = MatchParameters (luaState, methodDelegate, ref validDelegate);
if (isOk) {
object result;
if (methodDelegate.IsStatic)
result = methodDelegate.Invoke (null, validDelegate.args);
else
result = methodDelegate.Invoke (del.Target, validDelegate.args);
translator.Push (luaState, result);
return 1;
}
translator.ThrowError (luaState, "Cannot invoke delegate (invalid arguments for " + methodDelegate.Name + ")");
LuaLib.LuaPushNil (luaState);
return 1;
}
/* /*
* __call metafunction of type references. Searches for and calls * __call metafunction of type references. Searches for and calls
* a constructor for the type. Returns nil if the constructor is not * a constructor for the type. Returns nil if the constructor is not
......
...@@ -571,6 +571,7 @@ namespace NLua ...@@ -571,6 +571,7 @@ namespace NLua
PushObject (luaState, func, "luaNet_function"); PushObject (luaState, func, "luaNet_function");
} }
/* /*
* Pushes a CLR object into the Lua stack as an userdata * Pushes a CLR object into the Lua stack as an userdata
* with the provided metatable * with the provided metatable
...@@ -651,6 +652,7 @@ namespace NLua ...@@ -651,6 +652,7 @@ namespace NLua
LuaLib.LuaRawSet (luaState, -3); LuaLib.LuaRawSet (luaState, -3);
// Bind C# operator with Lua metamethods (__add, __sub, __mul) // Bind C# operator with Lua metamethods (__add, __sub, __mul)
RegisterOperatorsFunctions (luaState, o.GetType ()); RegisterOperatorsFunctions (luaState, o.GetType ());
RegisterCallMethodForDelegate (luaState, o);
} }
} else } else
LuaLib.LuaLGetMetatable (luaState, metatable); LuaLib.LuaLGetMetatable (luaState, metatable);
...@@ -667,6 +669,16 @@ namespace NLua ...@@ -667,6 +669,16 @@ namespace NLua
LuaLib.LuaRemove (luaState, -2); LuaLib.LuaRemove (luaState, -2);
} }
void RegisterCallMethodForDelegate (LuaState luaState, object o)
{
if (!(o is Delegate))
return;
LuaLib.LuaPushString (luaState, "__call");
LuaLib.LuaPushStdCallCFunction (luaState, metaFunctions.CallDelegateFunction);
LuaLib.LuaRawSet (luaState, -3);
}
void RegisterOperatorsFunctions (LuaState luaState, Type type) void RegisterOperatorsFunctions (LuaState luaState, Type type)
{ {
if (type.HasAdditionOpertator ()) { if (type.HasAdditionOpertator ()) {
......
...@@ -45,6 +45,14 @@ namespace NLuaTest ...@@ -45,6 +45,14 @@ namespace NLuaTest
} }
} }
#if MONOTOUCH
[Preserve (AllMembers = true)]
#endif
public class DefaultElementModel
{
public Action<double> DrawMe{ get; set; }
}
#if MONOTOUCH #if MONOTOUCH
[Preserve (AllMembers = true)] [Preserve (AllMembers = true)]
#endif #endif
...@@ -2239,6 +2247,68 @@ namespace NLuaTest ...@@ -2239,6 +2247,68 @@ namespace NLuaTest
} }
} }
[Test]
public void TestPushLuaFunctionWhenReadingDelegateProperty ()
{
bool called = false;
var _model = new DefaultElementModel ();
_model.DrawMe = (x) => {
called = true;
};
using (var l = new Lua ()) {
l ["model"] = _model;
l.DoString (@" model.DrawMe (0) ");
}
Assert.True (called);
}
[Test]
public void TestCallDelegateWithParameters ()
{
string sval = "";
int nval = 0;
using (var l = new Lua ()) {
Action<string,int> c = (s, n) => { sval = s; nval = n; };
l ["d"] = c;
l.DoString (" d ('string', 10) ");
}
Assert.AreEqual ("string", sval, "#1");
Assert.AreEqual (10 , nval, "#2");
}
[Test]
public void TestCallSimpleDelegate ()
{
bool called = false;
using (var l = new Lua ()) {
Action c = () => { called = true; };
l ["d"] = c;
l.DoString (" d () ");
}
Assert.True (called);
}
[Test]
public void TestCallDelegateWithWrongParametersShouldFail ()
{
bool fail = false;
using (var l = new Lua ()) {
Action c = () => { fail = false; };
l ["d"] = c;
try {
l.DoString (" d (10) ");
}
catch (LuaScriptException e) {
fail = true;
}
}
Assert.True (fail);
}
static Lua m_lua; static Lua m_lua;
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment