Last active
August 29, 2015 14:00
-
-
Save gocha/11390609 to your computer and use it in GitHub Desktop.
BizHawk: vargs support for LuaInterface (ported from NLua <https://github.com/NLua/NLua>, thanks a lot). Dirty test: <http://pastebin.com/d03N93z8>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Index: LuaInterface/LuaInterface/Metatables.cs | |
=================================================================== | |
--- LuaInterface/LuaInterface/Metatables.cs (revision 6441) | |
+++ LuaInterface/LuaInterface/Metatables.cs (working copy) | |
@@ -745,6 +745,55 @@ | |
LuaDLL.lua_pushnil(luaState); | |
return 1; | |
} | |
+ private static bool IsInteger(double x) { | |
+ return Math.Ceiling(x) == x; | |
+ } | |
+ | |
+ internal Array TableToArray (Func<int, object> luaParamValueExtractor, Type paramArrayType, int startIndex, int count) | |
+ { | |
+ Array paramArray; | |
+ | |
+ if (count == 0) | |
+ return Array.CreateInstance (paramArrayType, 0); | |
+ | |
+ var luaParamValue = luaParamValueExtractor (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.GetType () == typeof (double) && IsInteger ((double)value)) | |
+ value = Convert.ToInt32 ((double)value); | |
+ } | |
+ paramArray.SetValue (Convert.ChangeType (value, paramArrayType), paramArrayIndex); | |
+ paramArrayIndex++; | |
+ } | |
+ } else { | |
+ | |
+ paramArray = Array.CreateInstance (paramArrayType, count); | |
+ | |
+ paramArray.SetValue (luaParamValue, 0); | |
+ | |
+ for (int i = 1; i < count; i++) { | |
+ startIndex++; | |
+ var value = luaParamValueExtractor (startIndex); | |
+ paramArray.SetValue (value, i); | |
+ } | |
+ } | |
+ | |
+ return paramArray; | |
+ | |
+ } | |
+ | |
/* | |
* Matches a method against its arguments in the Lua stack. Returns | |
* if the match was succesful. It it was also returns the information | |
@@ -754,104 +803,76 @@ | |
{ | |
ExtractValue extractValue; | |
bool isMethod = true; | |
- ParameterInfo[] paramInfo = method.GetParameters(); | |
+ var paramInfo = method.GetParameters (); | |
int currentLuaParam = 1; | |
int nLuaParams = LuaDLL.lua_gettop(luaState); | |
- ArrayList paramList = new ArrayList(); | |
- List<int> outList = new List<int>(); | |
- List<MethodArgs> argTypes = new List<MethodArgs>(); | |
- foreach (ParameterInfo currentNetParam in paramInfo) | |
- { | |
- if (!currentNetParam.IsIn && currentNetParam.IsOut) // Skips out params | |
+ var paramList = new List<object> (); | |
+ var outList = new List<int> (); | |
+ var argTypes = new List<MethodArgs> (); | |
+ | |
+ foreach (var currentNetParam in paramInfo) { | |
+ if (!currentNetParam.IsIn && currentNetParam.IsOut) // Skips out params | |
{ | |
- outList.Add(paramList.Add(null)); | |
- } | |
- else if (currentLuaParam > nLuaParams) // Adds optional parameters | |
- { | |
- if (currentNetParam.IsOptional) | |
- { | |
- paramList.Add(currentNetParam.DefaultValue); | |
- } | |
- else | |
- { | |
- isMethod = false; | |
- break; | |
- } | |
- } | |
- else if (_IsTypeCorrect(luaState, currentLuaParam, currentNetParam, out extractValue)) // Type checking | |
- { | |
- int index = paramList.Add(extractValue(luaState, currentLuaParam)); | |
- | |
- MethodArgs methodArg = new MethodArgs(); | |
+ paramList.Add (null); | |
+ outList.Add (paramList.LastIndexOf (null)); | |
+ } else if (_IsTypeCorrect (luaState, currentLuaParam, currentNetParam, out extractValue)) { // Type checking | |
+ var value = extractValue (luaState, currentLuaParam); | |
+ paramList.Add (value); | |
+ int index = paramList.LastIndexOf (value); | |
+ var methodArg = new MethodArgs (); | |
methodArg.index = index; | |
methodArg.extractValue = extractValue; | |
- argTypes.Add(methodArg); | |
+ argTypes.Add (methodArg); | |
if (currentNetParam.ParameterType.IsByRef) | |
- outList.Add(index); | |
+ outList.Add (index); | |
+ | |
currentLuaParam++; | |
} // Type does not match, ignore if the parameter is optional | |
- else if (_IsParamsArray(luaState, currentLuaParam, currentNetParam, out extractValue)) | |
- { | |
- object luaParamValue = extractValue(luaState, currentLuaParam); | |
+ else if (_IsParamsArray (luaState, currentLuaParam, currentNetParam, out extractValue)) { | |
- Type paramArrayType = currentNetParam.ParameterType.GetElementType(); | |
+ var paramArrayType = currentNetParam.ParameterType.GetElementType (); | |
- Array paramArray; | |
+ Func<int, object> extractDelegate = (currentParam) => { | |
+ currentLuaParam ++; | |
+ return extractValue (luaState, currentParam); | |
+ }; | |
+ int count = (nLuaParams - currentLuaParam) + 1; | |
+ Array paramArray = TableToArray (extractDelegate, paramArrayType, currentLuaParam, count); | |
- if (luaParamValue is LuaTable) | |
- { | |
- LuaTable table = (LuaTable)luaParamValue; | |
- IDictionaryEnumerator tableEnumerator = table.GetEnumerator(); | |
- | |
- paramArray = Array.CreateInstance(paramArrayType, table.Values.Count); | |
- | |
- tableEnumerator.Reset(); | |
- | |
- int paramArrayIndex = 0; | |
- | |
- while(tableEnumerator.MoveNext()) | |
- { | |
- paramArray.SetValue(Convert.ChangeType(tableEnumerator.Value, currentNetParam.ParameterType.GetElementType()), paramArrayIndex); | |
- paramArrayIndex++; | |
- } | |
- } | |
- else | |
- { | |
- paramArray = Array.CreateInstance(paramArrayType, 1); | |
- paramArray.SetValue(luaParamValue, 0); | |
- } | |
- | |
- int index = paramList.Add(paramArray); | |
- | |
- MethodArgs methodArg = new MethodArgs(); | |
+ paramList.Add (paramArray); | |
+ int index = paramList.LastIndexOf (paramArray); | |
+ var methodArg = new MethodArgs (); | |
methodArg.index = index; | |
methodArg.extractValue = extractValue; | |
methodArg.isParamsArray = true; | |
methodArg.paramsArrayType = paramArrayType; | |
- argTypes.Add(methodArg); | |
+ argTypes.Add (methodArg); | |
- currentLuaParam++; | |
- } | |
- else if (currentNetParam.IsOptional) | |
- { | |
- paramList.Add(currentNetParam.DefaultValue); | |
- } | |
- else // No match | |
- { | |
+ } else if (currentLuaParam > nLuaParams) { // Adds optional parameters | |
+ if (currentNetParam.IsOptional) | |
+ paramList.Add (currentNetParam.DefaultValue); | |
+ else { | |
+ isMethod = false; | |
+ break; | |
+ } | |
+ } else if (currentNetParam.IsOptional) | |
+ paramList.Add (currentNetParam.DefaultValue); | |
+ else { // No match | |
isMethod = false; | |
break; | |
} | |
} | |
+ | |
if (currentLuaParam != nLuaParams + 1) // Number of parameters does not match | |
isMethod = false; | |
- if (isMethod) | |
- { | |
- methodCache.args = paramList.ToArray(); | |
+ if (isMethod) { | |
+ methodCache.args = paramList.ToArray (); | |
methodCache.cachedMethod = method; | |
- methodCache.outList = outList.ToArray(); | |
- methodCache.argTypes = argTypes.ToArray(); | |
+ methodCache.outList = outList.ToArray (); | |
+ methodCache.argTypes = argTypes.ToArray (); | |
} | |
+ | |
return isMethod; | |
} | |
Index: LuaInterface/LuaInterface/MethodWrapper.cs | |
=================================================================== | |
--- LuaInterface/LuaInterface/MethodWrapper.cs (revision 6441) | |
+++ LuaInterface/LuaInterface/MethodWrapper.cs (working copy) | |
@@ -158,6 +158,7 @@ | |
{ | |
int numStackToSkip = isStatic ? 0 : 1; // If this is an instance invoe we will have an extra arg on the stack for the targetObject | |
int numArgsPassed = LuaDLL.lua_gettop(luaState) - numStackToSkip; | |
+ MethodBase method = _LastCalledMethod.cachedMethod; | |
if (numArgsPassed == _LastCalledMethod.argTypes.Length) // No. of args match? | |
{ | |
@@ -164,42 +165,27 @@ | |
if (!LuaDLL.lua_checkstack(luaState, _LastCalledMethod.outList.Length + 6)) | |
throw new LuaException("Lua stack overflow"); | |
+ object [] args = _LastCalledMethod.args; | |
+ | |
try | |
{ | |
for (int i = 0; i < _LastCalledMethod.argTypes.Length; i++) | |
{ | |
- if (_LastCalledMethod.argTypes[i].isParamsArray) | |
- { | |
- object luaParamValue = _LastCalledMethod.argTypes[i].extractValue(luaState, i + 1 + numStackToSkip); | |
+ MethodArgs type = _LastCalledMethod.argTypes [i]; | |
- Type paramArrayType = _LastCalledMethod.argTypes[i].paramsArrayType; | |
+ int index = i + 1 + numStackToSkip; | |
- Array paramArray; | |
+ Func<int, object> valueExtractor = (currentParam) => { | |
+ return type.extractValue (luaState, currentParam); | |
+ }; | |
- if (luaParamValue is LuaTable) | |
- { | |
- LuaTable table = (LuaTable)luaParamValue; | |
- | |
- paramArray = Array.CreateInstance(paramArrayType, table.Values.Count); | |
- | |
- for (int x = 1; x <= table.Values.Count; x++) | |
- { | |
- paramArray.SetValue(Convert.ChangeType(table[x], paramArrayType), x - 1); | |
- } | |
- } | |
- else | |
- { | |
- paramArray = Array.CreateInstance(paramArrayType, 1); | |
- paramArray.SetValue(luaParamValue, 0); | |
- } | |
- | |
- _LastCalledMethod.args[_LastCalledMethod.argTypes[i].index] = paramArray; | |
+ if (_LastCalledMethod.argTypes [i].isParamsArray) { | |
+ int count = index - _LastCalledMethod.argTypes.Length; | |
+ Array paramArray = _Translator.TableToArray (valueExtractor, type.paramsArrayType, index, count); | |
+ args [_LastCalledMethod.argTypes [i].index] = paramArray; | |
+ } else { | |
+ args [type.index] = valueExtractor (index); | |
} | |
- else | |
- { | |
- _LastCalledMethod.args[_LastCalledMethod.argTypes[i].index] = | |
- _LastCalledMethod.argTypes[i].extractValue(luaState, i + 1 + numStackToSkip); | |
- } | |
if (_LastCalledMethod.args[_LastCalledMethod.argTypes[i].index] == null && | |
!LuaDLL.lua_isnil(luaState, i + 1 + numStackToSkip)) | |
Index: LuaInterface/LuaInterface/ObjectTranslator.cs | |
=================================================================== | |
--- LuaInterface/LuaInterface/ObjectTranslator.cs (revision 6441) | |
+++ LuaInterface/LuaInterface/ObjectTranslator.cs (working copy) | |
@@ -815,5 +815,9 @@ | |
{ | |
return metaFunctions.matchParameters(luaState,method,ref methodCache); | |
} | |
+ | |
+ internal Array TableToArray(Func<int, object> luaParamValue, Type paramArrayType, int startIndex, int count) { | |
+ return metaFunctions.TableToArray(luaParamValue,paramArrayType, startIndex, count); | |
+ } | |
} | |
} | |
\ No newline at end of file |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment