Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
ruanhaishen
NLua
Commits
27e4f04c
Commit
27e4f04c
authored
Oct 25, 2014
by
Vinicius Jarina
Browse files
Fixed call delegate functions.
Automatically register metamethod __call for delegate types. + Unit tests.
parent
d7f1849b
Changes
4
Show whitespace changes
Inline
Side-by-side
ConsoleTest/Program.cs
View file @
27e4f04c
...
...
@@ -10,14 +10,17 @@ using NLuaTest;
namespace
ConsoleTest
{
public
class
Program
{
static
void
Main
(
string
[]
args
)
{
Core
c
=
new
Core
();
c
.
Setup
();
c
.
Sieve
();
using
(
var
l
=
new
Lua
())
{
Action
c
=
()
=>
{
Console
.
WriteLine
(
"Ola"
);
};
l
[
"d"
]
=
c
;
l
.
DoString
(
" d () "
);
}
}
}
}
Core/NLua/Metatables.cs
View file @
27e4f04c
...
...
@@ -61,6 +61,7 @@ namespace NLua
public
LuaNativeFunction
ExecuteDelegateFunction
{
get
;
private
set
;
}
public
LuaNativeFunction
CallConstructorFunction
{
get
;
private
set
;
}
public
LuaNativeFunction
ToStringFunction
{
get
;
private
set
;
}
public
LuaNativeFunction
CallDelegateFunction
{
get
;
private
set
;
}
public
LuaNativeFunction
AddFunction
{
get
;
private
set
;
}
public
LuaNativeFunction
SubtractFunction
{
get
;
private
set
;
}
...
...
@@ -109,6 +110,7 @@ namespace NLua
ClassIndexFunction
=
new
LuaNativeFunction
(
MetaFunctions
.
GetClassMethod
);
ClassNewindexFunction
=
new
LuaNativeFunction
(
MetaFunctions
.
SetClassFieldOrProperty
);
ExecuteDelegateFunction
=
new
LuaNativeFunction
(
MetaFunctions
.
RunFunctionDelegate
);
CallDelegateFunction
=
new
LuaNativeFunction
(
MetaFunctions
.
CallDelegate
);
AddFunction
=
new
LuaNativeFunction
(
MetaFunctions
.
AddLua
);
SubtractFunction
=
new
LuaNativeFunction
(
MetaFunctions
.
SubtractLua
);
MultiplyFunction
=
new
LuaNativeFunction
(
MetaFunctions
.
MultiplyLua
);
...
...
@@ -605,7 +607,16 @@ namespace NLua
SetMemberCache
(
memberCache
,
objType
,
methodName
,
member
);
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
{
LuaLib
.
LuaPushNil
(
luaState
);
}
...
...
@@ -619,8 +630,16 @@ namespace NLua
SetMemberCache
(
memberCache
,
objType
,
methodName
,
member
);
try
{
object
val
=
property
.
GetValue
(
obj
,
null
);
translator
.
Push
(
luaState
,
val
);
object
value
=
property
.
GetValue
(
obj
,
null
);
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
)
{
// If we can't find the getter in our class, recurse up to the base class and see
// if they can help.
...
...
@@ -1006,6 +1025,53 @@ namespace NLua
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
* a constructor for the type. Returns nil if the constructor is not
...
...
Core/NLua/ObjectTranslator.cs
View file @
27e4f04c
...
...
@@ -571,6 +571,7 @@ namespace NLua
PushObject
(
luaState
,
func
,
"luaNet_function"
);
}
/*
* Pushes a CLR object into the Lua stack as an userdata
* with the provided metatable
...
...
@@ -651,6 +652,7 @@ namespace NLua
LuaLib
.
LuaRawSet
(
luaState
,
-
3
);
// Bind C# operator with Lua metamethods (__add, __sub, __mul)
RegisterOperatorsFunctions
(
luaState
,
o
.
GetType
());
RegisterCallMethodForDelegate
(
luaState
,
o
);
}
}
else
LuaLib
.
LuaLGetMetatable
(
luaState
,
metatable
);
...
...
@@ -667,6 +669,16 @@ namespace NLua
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
)
{
if
(
type
.
HasAdditionOpertator
())
{
...
...
tests/LuaTests.cs
View file @
27e4f04c
...
...
@@ -45,6 +45,14 @@ namespace NLuaTest
}
}
#
if
MONOTOUCH
[
Preserve
(
AllMembers
=
true
)]
#
endif
public
class
DefaultElementModel
{
public
Action
<
double
>
DrawMe
{
get
;
set
;
}
}
#
if
MONOTOUCH
[
Preserve
(
AllMembers
=
true
)]
#
endif
...
...
@@ -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
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment