Skip to content

Instantly share code, notes, and snippets.

@gocha
Last active August 29, 2015 14:00
Show Gist options
  • Save gocha/11390609 to your computer and use it in GitHub Desktop.
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>
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