Unverified Commit 251f40a9 authored by Roberto Iffland's avatar Roberto Iffland Committed by GitHub
Browse files

Changed the handling of variadic arguments. A Table doesn't work as a range of...


Changed the handling of variadic arguments. A Table doesn't work as a range of values anymore. (#476)
Co-authored-by: default avatarRoberto Iffland <roberto.iffland@spektra-dresden.com>
parent 4783440b
...@@ -1477,62 +1477,21 @@ namespace NLua ...@@ -1477,62 +1477,21 @@ namespace NLua
return 1; return 1;
} }
internal Array TableToArray(LuaState luaState, ExtractValue extractValue, Type paramArrayType, ref int startIndex, int count) /*
* Creates an array for the given range of arguments. The range is [startIndex .. startIndex + count).
* Usage scenario: Mapping a number of arguments (all remaining) to a 'params' declared parameter.
*/
internal static Array CreateParamsArray(LuaState luaState, ExtractValue extractValue, Type paramArrayType, int startIndex, int count)
{ {
Array paramArray; var paramArray = Array.CreateInstance(paramArrayType, count);
for (int i = 0; i < count; i++)
if (count == 0)
return Array.CreateInstance(paramArrayType, 0);
var luaParamValue = extractValue(luaState, startIndex);
startIndex++;
if (luaParamValue is LuaTable)
{
LuaTable table = (LuaTable)luaParamValue;
IDictionaryEnumerator tableEnumerator = table.GetEnumerator();
tableEnumerator.Reset();
paramArray = Array.CreateInstance(paramArrayType, table.Values.Count);
int paramArrayIndex = 0;
while (tableEnumerator.MoveNext())
{
object value = tableEnumerator.Value;
if (paramArrayType == typeof(object))
{
if (value != null && value is double && IsInteger((double)value))
value = Convert.ToInt32((double)value);
}
if (typeof(IConvertible).IsAssignableFrom(value.GetType()))
{
paramArray.SetValue(Convert.ChangeType(value, paramArrayType), paramArrayIndex);
}
else
{
paramArray.SetValue(value, paramArrayIndex);
}
paramArrayIndex++;
}
}
else
{ {
paramArray = Array.CreateInstance(paramArrayType, count); var value = extractValue(luaState, startIndex);
paramArray.SetValue(value, i);
paramArray.SetValue(luaParamValue, 0); startIndex++;
for (int i = 1; i < count; i++)
{
var value = extractValue(luaState, startIndex);
paramArray.SetValue(value, i);
startIndex++;
}
} }
return paramArray; return paramArray;
} }
/* /*
...@@ -1564,7 +1523,8 @@ namespace NLua ...@@ -1564,7 +1523,8 @@ namespace NLua
int count = (nLuaParams - currentLuaParam) + 1; int count = (nLuaParams - currentLuaParam) + 1;
Type paramArrayType = currentNetParam.ParameterType.GetElementType(); Type paramArrayType = currentNetParam.ParameterType.GetElementType();
Array paramArray = TableToArray(luaState, extractValue, paramArrayType, ref currentLuaParam, count); Array paramArray = CreateParamsArray(luaState, extractValue, paramArrayType, currentLuaParam, count);
currentLuaParam += count;
paramList.Add(paramArray); paramList.Add(paramArray);
int index = paramList.LastIndexOf(paramArray); int index = paramList.LastIndexOf(paramArray);
var methodArg = new MethodArgs(); var methodArg = new MethodArgs();
......
...@@ -122,15 +122,15 @@ namespace NLua.Method ...@@ -122,15 +122,15 @@ namespace NLua.Method
if (_lastCalledMethod.argTypes[i].IsParamsArray) if (_lastCalledMethod.argTypes[i].IsParamsArray)
{ {
int count = _lastCalledMethod.argTypes.Length - i; int count = _lastCalledMethod.argTypes.Length - i;
Array paramArray = _translator.TableToArray(luaState, type.ExtractValue, type.ParameterType, index, count); Array paramArray = _translator.CreateParamsArray(luaState, type.ExtractValue, type.ParameterType, index, count);
args[_lastCalledMethod.argTypes[i].Index] = paramArray; args[_lastCalledMethod.argTypes[i].Index] = paramArray;
} }
else else
{ {
args[type.Index] = type.ExtractValue(luaState, index); args[type.Index] = type.ExtractValue(luaState, index);
} }
if (_lastCalledMethod.args[_lastCalledMethod.argTypes[i].Index] == null && if (_lastCalledMethod.args[_lastCalledMethod.argTypes[i].Index] == null &&
!luaState.IsNil(i + 1 + numStackToSkip)) !luaState.IsNil(i + 1 + numStackToSkip))
throw new LuaException(string.Format("Argument number {0} is invalid", (i + 1))); throw new LuaException(string.Format("Argument number {0} is invalid", (i + 1)));
} }
......
...@@ -1085,9 +1085,9 @@ namespace NLua ...@@ -1085,9 +1085,9 @@ namespace NLua
return metaFunctions.MatchParameters(luaState, method, methodCache, skipParam); return metaFunctions.MatchParameters(luaState, method, methodCache, skipParam);
} }
internal Array TableToArray(LuaState luaState, ExtractValue extractValue, Type paramArrayType, int startIndex, int count) internal Array CreateParamsArray(LuaState luaState, ExtractValue extractValue, Type paramArrayType, int startIndex, int count)
{ {
return metaFunctions.TableToArray(luaState, extractValue, paramArrayType, ref startIndex, count); return MetaFunctions.CreateParamsArray(luaState, extractValue, paramArrayType, startIndex, count);
} }
private Type TypeOf(LuaState luaState, int idx) private Type TypeOf(LuaState luaState, int idx)
......
using System; using System;
using System.Text; using System.Text;
using System.Reflection; using System.Reflection;
using System.Threading; using System.Threading;
...@@ -1193,6 +1193,21 @@ namespace NLuaTest ...@@ -1193,6 +1193,21 @@ namespace NLuaTest
} }
} }
/* /*
* Tests invocation of a method with a variadic argument list.
* This should work with zero or more arguments and any argument type, e.g. no unpacking/ conversion of Lua tables.
*/
[Test]
public void CallObjectMethodVarArgs()
{
using (Lua lua = new Lua())
{
lua["netobj"] = new TestTypes.TestClass();
Assert.AreEqual(0, (long)lua.DoString("return netobj:vararg()")[0]);
Assert.AreEqual(4, (long)lua.DoString("return netobj:vararg(true, nil, 1.2, '3')")[0]);
Assert.AreEqual(1, (long)lua.DoString("return netobj:vararg{true, nil, 1.2, '3'}")[0]);
}
}
/*
* Tests calling of an object's method with no overloading * Tests calling of an object's method with no overloading
* and out parameters * and out parameters
*/ */
...@@ -2834,17 +2849,19 @@ namespace NLuaTest ...@@ -2834,17 +2849,19 @@ namespace NLuaTest
} }
} }
/*
* A variadic function should except any number of arguments. A Lua table shouldn't
* be understood as an array of arguments but as a single argument (like any other type).
*/
[Test] [Test]
public void CallStaticMethod() public void CallStaticVarArgsFunction()
{ {
using (var lua = new Lua()) using (var lua = new Lua())
{ {
lua.DoString("FakeType = {}"); lua["f"] = (Func<object[], int>)TestClass.MethodWithObjectParams;
lua["FakeType.bar"] = (Func<object[],int>) TestClass.MethodWithObjectParams; Assert.AreEqual(1, (long)lua.DoString("return f{'one', 1}")[0]);
Assert.AreEqual(2, (long)lua.DoString("return f({'one', 1}, true)")[0]);
lua.DoString("i = FakeType.bar('one', 1)"); Assert.AreEqual(0, (long)lua.DoString("return f()")[0]);
Assert.AreEqual(2, lua["i"], "#1");
} }
} }
......
...@@ -146,6 +146,14 @@ namespace NLuaTest.TestTypes ...@@ -146,6 +146,14 @@ namespace NLuaTest.TestTypes
return arg; return arg;
} }
/*
* Returns the number of arguments received.
*/
public int vararg(params object[] args)
{
return args.Length;
}
public int callDelegate1(TestDelegate1 del) public int callDelegate1(TestDelegate1 del)
{ {
return del(2, 3); return del(2, 3);
......
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