Commit 2271a771 authored by Vinicius Jarina's avatar Vinicius Jarina
Browse files

Fixed test on iOS (device)

parent bf8c5fe6
Subproject commit 31271cd6f1b77768e6f70b4848e22fbc96b17338 Subproject commit 980e734233b9273426ba853b7078fddbc1f07549
Subproject commit f6a5029fb6650fe1cb763de1adf0df2f76a2fab6 Subproject commit ed5b8b89e20a6e230e12da1059918f6609bde2eb
/* /*
* This file is part of LuaInterface. * This file is part of LuaInterface.
* *
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz. * Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/> * Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*/ */
using System; using System;
using System.Reflection; using System.Reflection;
using System.Collections.Generic; using System.Collections.Generic;
using LuaInterface.Method; using LuaInterface.Method;
using LuaInterface.Extensions; using LuaInterface.Extensions;
namespace LuaInterface namespace LuaInterface
{ {
using LuaCore = KeraLua.Lua; #if USE_KOPILUA
using LuaCore = KopiLua.Lua;
/* #else
* Type checking and conversion functions. using LuaCore = KeraLua.Lua;
* #endif
* Author: Fabio Mascarenhas
* Version: 1.0 /*
*/ * Type checking and conversion functions.
class CheckType *
{ * Author: Fabio Mascarenhas
private Dictionary<long, ExtractValue> extractValues = new Dictionary<long, ExtractValue> (); * Version: 1.0
private ExtractValue extractNetObject; */
private ObjectTranslator translator; class CheckType
{
public CheckType (ObjectTranslator translator) private Dictionary<long, ExtractValue> extractValues = new Dictionary<long, ExtractValue> ();
{ private ExtractValue extractNetObject;
this.translator = translator; private ObjectTranslator translator;
extractValues.Add (typeof(object).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsObject));
extractValues.Add (typeof(sbyte).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsSbyte)); public CheckType (ObjectTranslator translator)
extractValues.Add (typeof(byte).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsByte)); {
extractValues.Add (typeof(short).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsShort)); this.translator = translator;
extractValues.Add (typeof(ushort).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsUshort)); extractValues.Add (typeof(object).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsObject));
extractValues.Add (typeof(int).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsInt)); extractValues.Add (typeof(sbyte).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsSbyte));
extractValues.Add (typeof(uint).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsUint)); extractValues.Add (typeof(byte).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsByte));
extractValues.Add (typeof(long).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsLong)); extractValues.Add (typeof(short).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsShort));
extractValues.Add (typeof(ulong).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsUlong)); extractValues.Add (typeof(ushort).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsUshort));
extractValues.Add (typeof(double).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsDouble)); extractValues.Add (typeof(int).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsInt));
extractValues.Add (typeof(char).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsChar)); extractValues.Add (typeof(uint).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsUint));
extractValues.Add (typeof(float).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsFloat)); extractValues.Add (typeof(long).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsLong));
extractValues.Add (typeof(decimal).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsDecimal)); extractValues.Add (typeof(ulong).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsUlong));
extractValues.Add (typeof(bool).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsBoolean)); extractValues.Add (typeof(double).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsDouble));
extractValues.Add (typeof(string).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsString)); extractValues.Add (typeof(char).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsChar));
extractValues.Add (typeof(LuaFunction).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsFunction)); extractValues.Add (typeof(float).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsFloat));
extractValues.Add (typeof(LuaTable).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsTable)); extractValues.Add (typeof(decimal).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsDecimal));
extractValues.Add (typeof(LuaUserData).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsUserdata)); extractValues.Add (typeof(bool).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsBoolean));
extractNetObject = new ExtractValue (getAsNetObject); extractValues.Add (typeof(string).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsString));
} extractValues.Add (typeof(LuaFunction).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsFunction));
extractValues.Add (typeof(LuaTable).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsTable));
/* extractValues.Add (typeof(LuaUserData).TypeHandle.Value.ToInt64 (), new ExtractValue (getAsUserdata));
* Checks if the value at Lua stack index stackPos matches paramType, extractNetObject = new ExtractValue (getAsNetObject);
* returning a conversion function if it does and null otherwise. }
*/
internal ExtractValue getExtractor (IReflect paramType) /*
{ * Checks if the value at Lua stack index stackPos matches paramType,
return getExtractor (paramType.UnderlyingSystemType); * returning a conversion function if it does and null otherwise.
} */
internal ExtractValue getExtractor (IReflect paramType)
internal ExtractValue getExtractor (Type paramType) {
{ return getExtractor (paramType.UnderlyingSystemType);
if (paramType.IsByRef) }
paramType = paramType.GetElementType ();
internal ExtractValue getExtractor (Type paramType)
long runtimeHandleValue = paramType.TypeHandle.Value.ToInt64 (); {
return extractValues.ContainsKey (runtimeHandleValue) ? extractValues [runtimeHandleValue] : extractNetObject; if (paramType.IsByRef)
} paramType = paramType.GetElementType ();
internal ExtractValue checkType (LuaCore.lua_State luaState, int stackPos, Type paramType) long runtimeHandleValue = paramType.TypeHandle.Value.ToInt64 ();
{ return extractValues.ContainsKey (runtimeHandleValue) ? extractValues [runtimeHandleValue] : extractNetObject;
var luatype = LuaLib.lua_type (luaState, stackPos); }
if (paramType.IsByRef) internal ExtractValue checkType (LuaCore.lua_State luaState, int stackPos, Type paramType)
paramType = paramType.GetElementType (); {
var luatype = LuaLib.lua_type (luaState, stackPos);
var underlyingType = Nullable.GetUnderlyingType (paramType);
if (paramType.IsByRef)
if (!underlyingType.IsNull ()) paramType = paramType.GetElementType ();
paramType = underlyingType; // Silently convert nullable types to their non null requics
var underlyingType = Nullable.GetUnderlyingType (paramType);
long runtimeHandleValue = paramType.TypeHandle.Value.ToInt64 ();
if (!underlyingType.IsNull ())
if (paramType.Equals (typeof(object))) paramType = underlyingType; // Silently convert nullable types to their non null requics
return extractValues [runtimeHandleValue];
long runtimeHandleValue = paramType.TypeHandle.Value.ToInt64 ();
//CP: Added support for generic parameters
if (paramType.IsGenericParameter) { if (paramType.Equals (typeof(object)))
if (luatype == LuaTypes.Boolean) return extractValues [runtimeHandleValue];
return extractValues [typeof(bool).TypeHandle.Value.ToInt64 ()];
else if (luatype == LuaTypes.String) //CP: Added support for generic parameters
return extractValues [typeof(string).TypeHandle.Value.ToInt64 ()]; if (paramType.IsGenericParameter) {
else if (luatype == LuaTypes.Table) if (luatype == LuaTypes.Boolean)
return extractValues [typeof(LuaTable).TypeHandle.Value.ToInt64 ()]; return extractValues [typeof(bool).TypeHandle.Value.ToInt64 ()];
else if (luatype == LuaTypes.UserData) else if (luatype == LuaTypes.String)
return extractValues [typeof(object).TypeHandle.Value.ToInt64 ()]; return extractValues [typeof(string).TypeHandle.Value.ToInt64 ()];
else if (luatype == LuaTypes.Function) else if (luatype == LuaTypes.Table)
return extractValues [typeof(LuaFunction).TypeHandle.Value.ToInt64 ()]; return extractValues [typeof(LuaTable).TypeHandle.Value.ToInt64 ()];
else if (luatype == LuaTypes.Number) else if (luatype == LuaTypes.UserData)
return extractValues [typeof(double).TypeHandle.Value.ToInt64 ()]; return extractValues [typeof(object).TypeHandle.Value.ToInt64 ()];
//else else if (luatype == LuaTypes.Function)
//;//an unsupported type was encountered return extractValues [typeof(LuaFunction).TypeHandle.Value.ToInt64 ()];
} else if (luatype == LuaTypes.Number)
return extractValues [typeof(double).TypeHandle.Value.ToInt64 ()];
if (LuaLib.lua_isnumber (luaState, stackPos)) //else
return extractValues [runtimeHandleValue]; //;//an unsupported type was encountered
}
if (paramType == typeof(bool)) {
if (LuaLib.lua_isboolean (luaState, stackPos)) if (LuaLib.lua_isnumber (luaState, stackPos))
return extractValues [runtimeHandleValue]; return extractValues [runtimeHandleValue];
} else if (paramType == typeof(string)) {
if (LuaLib.lua_isstring (luaState, stackPos)) if (paramType == typeof(bool)) {
return extractValues [runtimeHandleValue]; if (LuaLib.lua_isboolean (luaState, stackPos))
else if (luatype == LuaTypes.Nil) return extractValues [runtimeHandleValue];
return extractNetObject; // kevinh - silently convert nil to a null string pointer } else if (paramType == typeof(string)) {
} else if (paramType == typeof(LuaTable)) { if (LuaLib.lua_isstring (luaState, stackPos))
if (luatype == LuaTypes.Table) return extractValues [runtimeHandleValue];
return extractValues [runtimeHandleValue]; else if (luatype == LuaTypes.Nil)
} else if (paramType == typeof(LuaUserData)) { return extractNetObject; // kevinh - silently convert nil to a null string pointer
if (luatype == LuaTypes.UserData) } else if (paramType == typeof(LuaTable)) {
return extractValues [runtimeHandleValue]; if (luatype == LuaTypes.Table)
} else if (paramType == typeof(LuaFunction)) { return extractValues [runtimeHandleValue];
if (luatype == LuaTypes.Function) } else if (paramType == typeof(LuaUserData)) {
return extractValues [runtimeHandleValue]; if (luatype == LuaTypes.UserData)
} else if (typeof(Delegate).IsAssignableFrom (paramType) && luatype == LuaTypes.Function) return extractValues [runtimeHandleValue];
return new ExtractValue (new DelegateGenerator (translator, paramType).extractGenerated); } else if (paramType == typeof(LuaFunction)) {
else if (paramType.IsInterface && luatype == LuaTypes.Table) if (luatype == LuaTypes.Function)
return new ExtractValue (new ClassGenerator (translator, paramType).extractGenerated); return extractValues [runtimeHandleValue];
else if ((paramType.IsInterface || paramType.IsClass) && luatype == LuaTypes.Nil) { } else if (typeof(Delegate).IsAssignableFrom (paramType) && luatype == LuaTypes.Function)
// kevinh - allow nil to be silently converted to null - extractNetObject will return null when the item ain't found return new ExtractValue (new DelegateGenerator (translator, paramType).extractGenerated);
return extractNetObject; else if (paramType.IsInterface && luatype == LuaTypes.Table)
} else if (LuaLib.lua_type (luaState, stackPos) == LuaTypes.Table) { return new ExtractValue (new ClassGenerator (translator, paramType).extractGenerated);
if (LuaLib.luaL_getmetafield (luaState, stackPos, "__index")) { else if ((paramType.IsInterface || paramType.IsClass) && luatype == LuaTypes.Nil) {
object obj = translator.getNetObject (luaState, -1); // kevinh - allow nil to be silently converted to null - extractNetObject will return null when the item ain't found
LuaLib.lua_settop (luaState, -2); return extractNetObject;
if (!obj.IsNull () && paramType.IsAssignableFrom (obj.GetType ())) } else if (LuaLib.lua_type (luaState, stackPos) == LuaTypes.Table) {
return extractNetObject; if (LuaLib.luaL_getmetafield (luaState, stackPos, "__index")) {
} else object obj = translator.getNetObject (luaState, -1);
return null; LuaLib.lua_settop (luaState, -2);
} else { if (!obj.IsNull () && paramType.IsAssignableFrom (obj.GetType ()))
object obj = translator.getNetObject (luaState, stackPos); return extractNetObject;
if (!obj.IsNull () && paramType.IsAssignableFrom (obj.GetType ())) } else
return extractNetObject; return null;
} } else {
object obj = translator.getNetObject (luaState, stackPos);
return null; if (!obj.IsNull () && paramType.IsAssignableFrom (obj.GetType ()))
} return extractNetObject;
}
/*
* The following functions return the value in the Lua stack return null;
* index stackPos as the desired type if it can, or null }
* otherwise.
*/ /*
private object getAsSbyte (LuaCore.lua_State luaState, int stackPos) * The following functions return the value in the Lua stack
{ * index stackPos as the desired type if it can, or null
sbyte retVal = (sbyte)LuaLib.lua_tonumber (luaState, stackPos); * otherwise.
if (retVal == 0 && !LuaLib.lua_isnumber (luaState, stackPos)) */
return null; private object getAsSbyte (LuaCore.lua_State luaState, int stackPos)
{
return retVal; sbyte retVal = (sbyte)LuaLib.lua_tonumber (luaState, stackPos);
} if (retVal == 0 && !LuaLib.lua_isnumber (luaState, stackPos))
return null;
private object getAsByte (LuaCore.lua_State luaState, int stackPos)
{ return retVal;
byte retVal = (byte)LuaLib.lua_tonumber (luaState, stackPos); }
if (retVal == 0 && !LuaLib.lua_isnumber (luaState, stackPos))
return null; private object getAsByte (LuaCore.lua_State luaState, int stackPos)
{
return retVal; byte retVal = (byte)LuaLib.lua_tonumber (luaState, stackPos);
} if (retVal == 0 && !LuaLib.lua_isnumber (luaState, stackPos))
return null;
private object getAsShort (LuaCore.lua_State luaState, int stackPos)
{ return retVal;
short retVal = (short)LuaLib.lua_tonumber (luaState, stackPos); }
if (retVal == 0 && !LuaLib.lua_isnumber (luaState, stackPos))
return null; private object getAsShort (LuaCore.lua_State luaState, int stackPos)
{
return retVal; short retVal = (short)LuaLib.lua_tonumber (luaState, stackPos);
} if (retVal == 0 && !LuaLib.lua_isnumber (luaState, stackPos))
return null;
private object getAsUshort (LuaCore.lua_State luaState, int stackPos)
{ return retVal;
ushort retVal = (ushort)LuaLib.lua_tonumber (luaState, stackPos); }
if (retVal == 0 && !LuaLib.lua_isnumber (luaState, stackPos))
return null; private object getAsUshort (LuaCore.lua_State luaState, int stackPos)
{
return retVal; ushort retVal = (ushort)LuaLib.lua_tonumber (luaState, stackPos);
} if (retVal == 0 && !LuaLib.lua_isnumber (luaState, stackPos))
return null;
private object getAsInt (LuaCore.lua_State luaState, int stackPos)
{ return retVal;
int retVal = (int)LuaLib.lua_tonumber (luaState, stackPos); }
if (retVal == 0 && !LuaLib.lua_isnumber (luaState, stackPos))
return null; private object getAsInt (LuaCore.lua_State luaState, int stackPos)
{
return retVal; int retVal = (int)LuaLib.lua_tonumber (luaState, stackPos);
} if (retVal == 0 && !LuaLib.lua_isnumber (luaState, stackPos))
return null;
private object getAsUint (LuaCore.lua_State luaState, int stackPos)
{ return retVal;
uint retVal = (uint)LuaLib.lua_tonumber (luaState, stackPos); }
if (retVal == 0 && !LuaLib.lua_isnumber (luaState, stackPos))
return null; private object getAsUint (LuaCore.lua_State luaState, int stackPos)
{
return retVal; uint retVal = (uint)LuaLib.lua_tonumber (luaState, stackPos);
} if (retVal == 0 && !LuaLib.lua_isnumber (luaState, stackPos))
return null;
private object getAsLong (LuaCore.lua_State luaState, int stackPos)
{ return retVal;
long retVal = (long)LuaLib.lua_tonumber (luaState, stackPos); }
if (retVal == 0 && !LuaLib.lua_isnumber (luaState, stackPos))
return null; private object getAsLong (LuaCore.lua_State luaState, int stackPos)
{
return retVal; long retVal = (long)LuaLib.lua_tonumber (luaState, stackPos);
} if (retVal == 0 && !LuaLib.lua_isnumber (luaState, stackPos))
return null;
private object getAsUlong (LuaCore.lua_State luaState, int stackPos)
{ return retVal;
ulong retVal = (ulong)LuaLib.lua_tonumber (luaState, stackPos); }
if (retVal == 0 && !LuaLib.lua_isnumber (luaState, stackPos))
return null; private object getAsUlong (LuaCore.lua_State luaState, int stackPos)
{
return retVal; ulong retVal = (ulong)LuaLib.lua_tonumber (luaState, stackPos);
} if (retVal == 0 && !LuaLib.lua_isnumber (luaState, stackPos))
return null;
private object getAsDouble (LuaCore.lua_State luaState, int stackPos)
{ return retVal;
double retVal = LuaLib.lua_tonumber (luaState, stackPos); }
if (retVal == 0 && !LuaLib.lua_isnumber (luaState, stackPos))
return null; private object getAsDouble (LuaCore.lua_State luaState, int stackPos)
{
return retVal; double retVal = LuaLib.lua_tonumber (luaState, stackPos);
} if (retVal == 0 && !LuaLib.lua_isnumber (luaState, stackPos))
return null;
private object getAsChar (LuaCore.lua_State luaState, int stackPos)
{ return retVal;
char retVal = (char)LuaLib.lua_tonumber (luaState, stackPos); }
if (retVal == 0 && !LuaLib.lua_isnumber (luaState, stackPos))
return null; private object getAsChar (LuaCore.lua_State luaState, int stackPos)
{
return retVal; char retVal = (char)LuaLib.lua_tonumber (luaState, stackPos);
} if (retVal == 0 && !LuaLib.lua_isnumber (luaState, stackPos))
return null;
private object getAsFloat (LuaCore.lua_State luaState, int stackPos)
{ return retVal;
float retVal = (float)LuaLib.lua_tonumber (luaState, stackPos); }
if (retVal == 0 && !LuaLib.lua_isnumber (luaState, stackPos))
return null; private object getAsFloat (LuaCore.lua_State luaState, int stackPos)
{
return retVal; float retVal = (float)LuaLib.lua_tonumber (luaState, stackPos);
} if (retVal == 0 && !LuaLib.lua_isnumber (luaState, stackPos))
return null;
private object getAsDecimal (LuaCore.lua_State luaState, int stackPos)
{ return retVal;
decimal retVal = (decimal)LuaLib.lua_tonumber (luaState, stackPos); }
if (retVal == 0 && !LuaLib.lua_isnumber (luaState, stackPos))
return null; private object getAsDecimal (LuaCore.lua_State luaState, int stackPos)
{
return retVal; decimal retVal = (decimal)LuaLib.lua_tonumber (luaState, stackPos);
} if (retVal == 0 && !LuaLib.lua_isnumber (luaState, stackPos))
return null;
private object getAsBoolean (LuaCore.lua_State luaState, int stackPos)
{ return retVal;
return LuaLib.lua_toboolean (luaState, stackPos); }
}
private object getAsBoolean (LuaCore.lua_State luaState, int stackPos)
private object getAsString (LuaCore.lua_State luaState, int stackPos) {
{ return LuaLib.lua_toboolean (luaState, stackPos);
string retVal = LuaLib.lua_tostring (luaState, stackPos).ToString (); }
if (retVal == string.Empty && !LuaLib.lua_isstring (luaState, stackPos))
return null; private object getAsString (LuaCore.lua_State luaState, int stackPos)
{
return retVal; string retVal = LuaLib.lua_tostring (luaState, stackPos).ToString ();
} if (retVal == string.Empty && !LuaLib.lua_isstring (luaState, stackPos))
return null;
private object getAsTable (LuaCore.lua_State luaState, int stackPos)
{ return retVal;
return translator.getTable (luaState, stackPos); }
}
private object getAsTable (LuaCore.lua_State luaState, int stackPos)
private object getAsFunction (LuaCore.lua_State luaState, int stackPos) {
{ return translator.getTable (luaState, stackPos);
return translator.getFunction (luaState, stackPos); }
}
private object getAsFunction (LuaCore.lua_State luaState, int stackPos)
private object getAsUserdata (LuaCore.lua_State luaState, int stackPos) {
{ return translator.getFunction (luaState, stackPos);
return translator.getUserData (luaState, stackPos); }
}
private object getAsUserdata (LuaCore.lua_State luaState, int stackPos)
public object getAsObject (LuaCore.lua_State luaState, int stackPos) {
{ return translator.getUserData (luaState, stackPos);
if (LuaLib.lua_type (luaState, stackPos) == LuaTypes.Table) { }
if (LuaLib.luaL_getmetafield (luaState, stackPos, "__index")) {
if (LuaLib.luaL_checkmetatable (luaState, -1)) { public object getAsObject (LuaCore.lua_State luaState, int stackPos)
LuaLib.lua_insert (luaState, stackPos); {
LuaLib.lua_remove (luaState, stackPos + 1); if (LuaLib.lua_type (luaState, stackPos) == LuaTypes.Table) {
} else if (LuaLib.luaL_getmetafield (luaState, stackPos, "__index")) {
LuaLib.lua_settop (luaState, -2); if (LuaLib.luaL_checkmetatable (luaState, -1)) {
} LuaLib.lua_insert (luaState, stackPos);
} LuaLib.lua_remove (luaState, stackPos + 1);
} else
object obj = translator.getObject (luaState, stackPos); LuaLib.lua_settop (luaState, -2);
return obj; }
} }
public object getAsNetObject (LuaCore.lua_State luaState, int stackPos) object obj = translator.getObject (luaState, stackPos);
{ return obj;
object obj = translator.getNetObject (luaState, stackPos); }
if (obj.IsNull () && LuaLib.lua_type (luaState, stackPos) == LuaTypes.Table) { public object getAsNetObject (LuaCore.lua_State luaState, int stackPos)
if (LuaLib.luaL_getmetafield (luaState, stackPos, "__index")) { {
if (LuaLib.luaL_checkmetatable (luaState, -1)) { object obj = translator.getNetObject (luaState, stackPos);
LuaLib.lua_insert (luaState, stackPos);
LuaLib.lua_remove (luaState, stackPos + 1); if (obj.IsNull () && LuaLib.lua_type (luaState, stackPos) == LuaTypes.Table) {
obj = translator.getNetObject (luaState, stackPos); if (LuaLib.luaL_getmetafield (luaState, stackPos, "__index")) {
} else if (LuaLib.luaL_checkmetatable (luaState, -1)) {
LuaLib.lua_settop (luaState, -2); LuaLib.lua_insert (luaState, stackPos);
} LuaLib.lua_remove (luaState, stackPos + 1);
} obj = translator.getNetObject (luaState, stackPos);
} else
return obj; LuaLib.lua_settop (luaState, -2);
} }
} }
return obj;
}
}
} }
\ No newline at end of file
/* /*
* This file is part of LuaInterface. * This file is part of LuaInterface.
* *
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz. * Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/> * Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*/ */
using System; using System;
namespace LuaInterface.Event namespace LuaInterface.Event
{ {
using LuaCore = KeraLua.Lua; #if USE_KOPILUA
using LuaCore = KopiLua.Lua;
/// <summary> #else
/// Event args for hook callback event using LuaCore = KeraLua.Lua;
/// </summary> #endif
/// <author>Reinhard Ostermeier</author>
public class DebugHookEventArgs : EventArgs /// <summary>
{ /// Event args for hook callback event
private readonly LuaCore.lua_Debug luaDebug; /// </summary>
/// <author>Reinhard Ostermeier</author>
public DebugHookEventArgs (LuaCore.lua_Debug luaDebug) public class DebugHookEventArgs : EventArgs
{ {
this.luaDebug = luaDebug; private readonly LuaCore.lua_Debug luaDebug;
}
public DebugHookEventArgs (LuaCore.lua_Debug luaDebug)
public LuaCore.lua_Debug LuaDebug { {
get { return luaDebug; } this.luaDebug = luaDebug;
} }
}
public LuaCore.lua_Debug LuaDebug {
get { return luaDebug; }
}
}
} }
\ No newline at end of file
/* /*
* This file is part of LuaInterface. * This file is part of LuaInterface.
* *
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/> * Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*/ */
using System; using System;
namespace LuaInterface.Extensions namespace LuaInterface.Extensions
{ {
/// <summary> /// <summary>
/// Some random extension stuff. /// Some random extension stuff.
/// </summary> /// </summary>
static class GeneralExtensions static class GeneralExtensions
{ {
/// <summary> /// <summary>
/// Determines whether the specified obj is null. /// Determines whether the specified obj is null.
/// </summary> /// </summary>
/// <param name="obj">The obj.</param> /// <param name="obj">The obj.</param>
/// <returns> /// <returns>
/// <c>true</c> if the specified obj is null; otherwise, <c>false</c>. /// <c>true</c> if the specified obj is null; otherwise, <c>false</c>.
/// </returns> /// </returns>
public static bool IsNull (this object obj) public static bool IsNull (this object obj)
{ {
return (obj == null); return (obj == null);
} }
public static bool IsNull (this IntPtr ptr) public static bool IsNull (this IntPtr ptr)
{ {
return (ptr == null || ptr.Equals (IntPtr.Zero)); return (ptr.Equals (IntPtr.Zero));
} }
} }
} }
\ No newline at end of file
/* /*
* This file is part of LuaInterface. * This file is part of LuaInterface.
* *
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz. * Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/> * Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*/ */
using System; using System;
namespace LuaInterface namespace LuaInterface
{ {
using LuaCore = KeraLua.Lua; #if USE_KOPILUA
/* using LuaCore = KopiLua.Lua;
* Class used for generating delegates that get a table from the Lua #else
* stack as a an object of a specific type. using LuaCore = KeraLua.Lua;
* #endif
* Author: Fabio Mascarenhas /*
* Version: 1.0 * Class used for generating delegates that get a table from the Lua
*/ * stack as a an object of a specific type.
class ClassGenerator *
{ * Author: Fabio Mascarenhas
private ObjectTranslator translator; * Version: 1.0
private Type klass; */
class ClassGenerator
public ClassGenerator (ObjectTranslator translator, Type klass) {
{ private ObjectTranslator translator;
this.translator = translator; private Type klass;
this.klass = klass;
} public ClassGenerator (ObjectTranslator translator, Type klass)
{
public object extractGenerated (LuaCore.lua_State luaState, int stackPos) this.translator = translator;
{ this.klass = klass;
return CodeGeneration.Instance.GetClassInstance (klass, translator.getTable (luaState, stackPos)); }
}
} public object extractGenerated (LuaCore.lua_State luaState, int stackPos)
{
return CodeGeneration.Instance.GetClassInstance (klass, translator.getTable (luaState, stackPos));
}
}
} }
\ No newline at end of file
/* /*
* This file is part of LuaInterface. * This file is part of LuaInterface.
* *
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz. * Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/> * Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*/ */
using System; using System;
namespace LuaInterface namespace LuaInterface
{ {
using LuaCore = KeraLua.Lua; #if USE_KOPILUA
/* using LuaCore = KopiLua.Lua;
* Class used for generating delegates that get a function from the Lua #else
* stack as a delegate of a specific type. using LuaCore = KeraLua.Lua;
* #endif
* Author: Fabio Mascarenhas /*
* Version: 1.0 * Class used for generating delegates that get a function from the Lua
*/ * stack as a delegate of a specific type.
class DelegateGenerator *
{ * Author: Fabio Mascarenhas
private ObjectTranslator translator; * Version: 1.0
private Type delegateType; */
class DelegateGenerator
{
public DelegateGenerator (ObjectTranslator translator, Type delegateType) private ObjectTranslator translator;
{ private Type delegateType;
this.translator = translator;
this.delegateType = delegateType;
} public DelegateGenerator (ObjectTranslator translator, Type delegateType)
{
public object extractGenerated (LuaCore.lua_State luaState, int stackPos) this.translator = translator;
{ this.delegateType = delegateType;
return CodeGeneration.Instance.GetDelegate (delegateType, translator.getFunction (luaState, stackPos)); }
}
} public object extractGenerated (LuaCore.lua_State luaState, int stackPos)
{
return CodeGeneration.Instance.GetDelegate (delegateType, translator.getFunction (luaState, stackPos));
}
}
} }
\ No newline at end of file
/* /*
* This file is part of LuaInterface. * This file is part of LuaInterface.
* *
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz. * Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/> * Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*/ */
using System; using System;
using System.IO; using System.IO;
using System.Threading; using System.Threading;
using System.Reflection; using System.Reflection;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized; using System.Collections.Specialized;
using LuaInterface.Event; using LuaInterface.Event;
using LuaInterface.Method; using LuaInterface.Method;
using LuaInterface.Exceptions; using LuaInterface.Exceptions;
using LuaInterface.Extensions; using LuaInterface.Extensions;
namespace LuaInterface namespace LuaInterface
{ {
using LuaCore = KeraLua.Lua; #if USE_KOPILUA
using LuaCore = KopiLua.Lua;
/* #else
* Main class of LuaInterface using LuaCore = KeraLua.Lua;
* Object-oriented wrapper to Lua API #endif
*
* Author: Fabio Mascarenhas /*
* Version: 1.0 * Main class of LuaInterface
* * Object-oriented wrapper to Lua API
* // steffenj: important changes in Lua class: *
* - removed all Open*Lib() functions * Author: Fabio Mascarenhas
* - all libs automatically open in the Lua class constructor (just assign nil to unwanted libs) * Version: 1.0
* */ *
[CLSCompliant(true)] * // steffenj: important changes in Lua class:
public class Lua : IDisposable * - removed all Open*Lib() functions
{ * - all libs automatically open in the Lua class constructor (just assign nil to unwanted libs)
#region lua debug functions * */
/// <summary> [CLSCompliant(true)]
/// Event that is raised when an exception occures during a hook call. public class Lua : IDisposable
/// </summary> {
/// <author>Reinhard Ostermeier</author> #region lua debug functions
public event EventHandler<HookExceptionEventArgs> HookException; /// <summary>
/// <summary> /// Event that is raised when an exception occures during a hook call.
/// Event when lua hook callback is called /// </summary>
/// </summary> /// <author>Reinhard Ostermeier</author>
/// <remarks> public event EventHandler<HookExceptionEventArgs> HookException;
/// Is only raised if SetDebugHook is called before. /// <summary>
/// </remarks> /// Event when lua hook callback is called
/// <author>Reinhard Ostermeier</author> /// </summary>
public event EventHandler<DebugHookEventArgs> DebugHook; /// <remarks>
/// <summary> /// Is only raised if SetDebugHook is called before.
/// lua hook calback delegate /// </remarks>
/// </summary> /// <author>Reinhard Ostermeier</author>
/// <author>Reinhard Ostermeier</author> public event EventHandler<DebugHookEventArgs> DebugHook;
private LuaCore.lua_Hook hookCallback = null; /// <summary>
#endregion /// lua hook calback delegate
#region Globals auto-complete /// </summary>
private readonly List<string> globals = new List<string> (); /// <author>Reinhard Ostermeier</author>
private bool globalsSorted; private LuaCore.lua_Hook hookCallback = null;
#endregion #endregion
private /*readonly */ LuaCore.lua_State luaState; #region Globals auto-complete
/// <summary> private readonly List<string> globals = new List<string> ();
/// True while a script is being executed private bool globalsSorted;
/// </summary> #endregion
public bool IsExecuting { get { return executing; } } private /*readonly */ LuaCore.lua_State luaState;
/// <summary>
private LuaCore.lua_CFunction panicCallback; /// True while a script is being executed
private ObjectTranslator translator; /// </summary>
/// <summary> public bool IsExecuting { get { return executing; } }
/// Used to ensure multiple .net threads all get serialized by this single lock for access to the lua stack/objects
/// </summary> private LuaCore.lua_CFunction panicCallback;
//private object luaLock = new object(); private ObjectTranslator translator;
private bool _StatePassed; /// <summary>
private bool executing; /// Used to ensure multiple .net threads all get serialized by this single lock for access to the lua stack/objects
static string init_luanet = /// </summary>
"local metatable = {} \n" + //private object luaLock = new object();
"local import_type = luanet.import_type \n" + private bool _StatePassed;
"local load_assembly = luanet.load_assembly \n" + private bool executing;
" \n" + static string init_luanet =
"-- Lookup a .NET identifier component. \n" + "local metatable = {} \n" +
"function metatable:__index(key) -- key is e.g. \"Form\" \n" + "local import_type = luanet.import_type \n" +
" -- Get the fully-qualified name, e.g. \"System.Windows.Forms.Form\" \n" + "local load_assembly = luanet.load_assembly \n" +
" local fqn = ((rawget(self, \".fqn\") and rawget(self, \".fqn\") .. \n" + " \n" +
" \".\") or \"\") .. key \n" + "-- Lookup a .NET identifier component. \n" +
" \n" + "function metatable:__index(key) -- key is e.g. \"Form\" \n" +
" -- Try to find either a luanet function or a CLR type \n" + " -- Get the fully-qualified name, e.g. \"System.Windows.Forms.Form\" \n" +
" local obj = rawget(luanet, key) or import_type(fqn) \n" + " local fqn = ((rawget(self, \".fqn\") and rawget(self, \".fqn\") .. \n" +
" \n" + " \".\") or \"\") .. key \n" +
" -- If key is neither a luanet function or a CLR type, then it is simply \n" + " \n" +
" -- an identifier component. \n" + " -- Try to find either a luanet function or a CLR type \n" +
" if obj == nil then \n" + " local obj = rawget(luanet, key) or import_type(fqn) \n" +
" -- It might be an assembly, so we load it too. \n" + " \n" +
" load_assembly(fqn) \n" + " -- If key is neither a luanet function or a CLR type, then it is simply \n" +
" obj = { [\".fqn\"] = fqn } \n" + " -- an identifier component. \n" +
" setmetatable(obj, metatable) \n" + " if obj == nil then \n" +
" end \n" + " -- It might be an assembly, so we load it too. \n" +
" \n" + " load_assembly(fqn) \n" +
" -- Cache this lookup \n" + " obj = { [\".fqn\"] = fqn } \n" +
" rawset(self, key, obj) \n" + " setmetatable(obj, metatable) \n" +
" return obj \n" + " end \n" +
"end \n" + " \n" +
" \n" + " -- Cache this lookup \n" +
"-- A non-type has been called; e.g. foo = System.Foo() \n" + " rawset(self, key, obj) \n" +
"function metatable:__call(...) \n" + " return obj \n" +
" error(\"No such type: \" .. rawget(self, \".fqn\"), 2) \n" + "end \n" +
"end \n" + " \n" +
" \n" + "-- A non-type has been called; e.g. foo = System.Foo() \n" +
"-- This is the root of the .NET namespace \n" + "function metatable:__call(...) \n" +
"luanet[\".fqn\"] = false \n" + " error(\"No such type: \" .. rawget(self, \".fqn\"), 2) \n" +
"setmetatable(luanet, metatable) \n" + "end \n" +
" \n" + " \n" +
"-- Preload the mscorlib assembly \n" + "-- This is the root of the .NET namespace \n" +
"luanet.load_assembly(\"mscorlib\") \n"; "luanet[\".fqn\"] = false \n" +
"setmetatable(luanet, metatable) \n" +
#region Globals auto-complete " \n" +
/// <summary> "-- Preload the mscorlib assembly \n" +
/// An alphabetically sorted list of all globals (objects, methods, etc.) externally added to this Lua instance "luanet.load_assembly(\"mscorlib\") \n";
/// </summary>
/// <remarks>Members of globals are also listed. The formatting is optimized for text input auto-completion.</remarks> #region Globals auto-complete
public IEnumerable<string> Globals { /// <summary>
get { /// An alphabetically sorted list of all globals (objects, methods, etc.) externally added to this Lua instance
// Only sort list when necessary /// </summary>
if (!globalsSorted) { /// <remarks>Members of globals are also listed. The formatting is optimized for text input auto-completion.</remarks>
globals.Sort (); public IEnumerable<string> Globals {
globalsSorted = true; get {
} // Only sort list when necessary
if (!globalsSorted) {
return globals; globals.Sort ();
} globalsSorted = true;
} }
#endregion
return globals;
public Lua () }
{ }
luaState = LuaLib.luaL_newstate (); // steffenj: Lua 5.1.1 API change (lua_open is gone) #endregion
//LuaLib.luaopen_base(luaState); // steffenj: luaopen_* no longer used
LuaLib.luaL_openlibs (luaState); // steffenj: Lua 5.1.1 API change (luaopen_base is gone, just open all libs right here) public Lua ()
LuaLib.lua_pushstring (luaState, "LUAINTERFACE LOADED"); {
LuaLib.lua_pushboolean (luaState, true); luaState = LuaLib.luaL_newstate (); // steffenj: Lua 5.1.1 API change (lua_open is gone)
LuaLib.lua_settable (luaState, (int)LuaIndexes.Registry); //LuaLib.luaopen_base(luaState); // steffenj: luaopen_* no longer used
LuaLib.lua_newtable (luaState); LuaLib.luaL_openlibs (luaState); // steffenj: Lua 5.1.1 API change (luaopen_base is gone, just open all libs right here)
LuaLib.lua_setglobal (luaState, "luanet"); LuaLib.lua_pushstring (luaState, "LUAINTERFACE LOADED");
LuaLib.lua_pushvalue (luaState, (int)LuaIndexes.Globals); LuaLib.lua_pushboolean (luaState, true);
LuaLib.lua_getglobal (luaState, "luanet"); LuaLib.lua_settable (luaState, (int)LuaIndexes.Registry);
LuaLib.lua_pushstring (luaState, "getmetatable"); LuaLib.lua_newtable (luaState);
LuaLib.lua_getglobal (luaState, "getmetatable"); LuaLib.lua_setglobal (luaState, "luanet");
LuaLib.lua_settable (luaState, -3); LuaLib.lua_pushvalue (luaState, (int)LuaIndexes.Globals);
LuaLib.lua_replace (luaState, (int)LuaIndexes.Globals); LuaLib.lua_getglobal (luaState, "luanet");
translator = new ObjectTranslator (this, luaState); LuaLib.lua_pushstring (luaState, "getmetatable");
LuaLib.lua_replace (luaState, (int)LuaIndexes.Globals); LuaLib.lua_getglobal (luaState, "getmetatable");
LuaLib.luaL_dostring (luaState, Lua.init_luanet); // steffenj: lua_dostring renamed to luaL_dostring LuaLib.lua_settable (luaState, -3);
LuaLib.lua_replace (luaState, (int)LuaIndexes.Globals);
// We need to keep this in a managed reference so the delegate doesn't get garbage collected translator = new ObjectTranslator (this, luaState);
panicCallback = new LuaCore.lua_CFunction (PanicCallback); ObjectTranslatorPool.Instance.Add (luaState, translator);
LuaLib.lua_atpanic (luaState, panicCallback); LuaLib.lua_replace (luaState, (int)LuaIndexes.Globals);
LuaLib.luaL_dostring (luaState, Lua.init_luanet); // steffenj: lua_dostring renamed to luaL_dostring
//LuaLib.lua_atlock(luaState, lockCallback = new LuaCore.lua_CFunction(LockCallback));
//LuaLib.lua_atunlock(luaState, unlockCallback = new LuaCore.lua_CFunction(UnlockCallback)); // We need to keep this in a managed reference so the delegate doesn't get garbage collected
} panicCallback = new LuaCore.lua_CFunction (PanicCallback);
LuaLib.lua_atpanic (luaState, panicCallback);
/*
* CAUTION: LuaInterface.Lua instances can't share the same lua state! //LuaLib.lua_atlock(luaState, lockCallback = new LuaCore.lua_CFunction(LockCallback));
*/ //LuaLib.lua_atunlock(luaState, unlockCallback = new LuaCore.lua_CFunction(UnlockCallback));
public Lua (LuaCore.lua_State lState) }
{
LuaLib.lua_pushstring (lState, "LUAINTERFACE LOADED"); /*
LuaLib.lua_gettable (lState, (int)LuaIndexes.Registry); * CAUTION: LuaInterface.Lua instances can't share the same lua state!
*/
if (LuaLib.lua_toboolean (lState, -1)) { public Lua (LuaCore.lua_State lState)
LuaLib.lua_settop (lState, -2); {
throw new LuaException ("There is already a LuaInterface.Lua instance associated with this Lua state"); LuaLib.lua_pushstring (lState, "LUAINTERFACE LOADED");
} else { LuaLib.lua_gettable (lState, (int)LuaIndexes.Registry);
LuaLib.lua_settop (lState, -2);
LuaLib.lua_pushstring (lState, "LUAINTERFACE LOADED"); if (LuaLib.lua_toboolean (lState, -1)) {
LuaLib.lua_pushboolean (lState, true); LuaLib.lua_settop (lState, -2);
LuaLib.lua_settable (lState, (int)LuaIndexes.Registry); throw new LuaException ("There is already a LuaInterface.Lua instance associated with this Lua state");
luaState = lState; } else {
LuaLib.lua_pushvalue (lState, (int)LuaIndexes.Globals); LuaLib.lua_settop (lState, -2);
LuaLib.lua_getglobal (lState, "luanet"); LuaLib.lua_pushstring (lState, "LUAINTERFACE LOADED");
LuaLib.lua_pushstring (lState, "getmetatable"); LuaLib.lua_pushboolean (lState, true);
LuaLib.lua_getglobal (lState, "getmetatable"); LuaLib.lua_settable (lState, (int)LuaIndexes.Registry);
LuaLib.lua_settable (lState, -3); luaState = lState;
LuaLib.lua_replace (lState, (int)LuaIndexes.Globals); LuaLib.lua_pushvalue (lState, (int)LuaIndexes.Globals);
translator = new ObjectTranslator (this, luaState); LuaLib.lua_getglobal (lState, "luanet");
LuaLib.lua_replace (lState, (int)LuaIndexes.Globals); LuaLib.lua_pushstring (lState, "getmetatable");
LuaLib.luaL_dostring (lState, Lua.init_luanet); // steffenj: lua_dostring renamed to luaL_dostring LuaLib.lua_getglobal (lState, "getmetatable");
} LuaLib.lua_settable (lState, -3);
LuaLib.lua_replace (lState, (int)LuaIndexes.Globals);
_StatePassed = true; translator = new ObjectTranslator (this, luaState);
} ObjectTranslatorPool.Instance.Add (luaState, translator);
LuaLib.lua_replace (lState, (int)LuaIndexes.Globals);
/// <summary> LuaLib.luaL_dostring (lState, Lua.init_luanet); // steffenj: lua_dostring renamed to luaL_dostring
/// Called for each lua_lock call }
/// </summary>
/// <param name = "luaState"></param> _StatePassed = true;
/// Not yet used }
/*int LockCallback(LuaCore.lua_State luaState)
{ /// <summary>
// Monitor.Enter(luaLock); /// Called for each lua_lock call
return 0; /// </summary>
}*/ /// <param name = "luaState"></param>
/// Not yet used
/// <summary> /*int LockCallback(LuaCore.lua_State luaState)
/// Called for each lua_unlock call {
/// </summary> // Monitor.Enter(luaLock);
/// <param name = "luaState"></param> return 0;
/// Not yet used }*/
/*int UnlockCallback(LuaCore.lua_State luaState)
{ /// <summary>
// Monitor.Exit(luaLock); /// Called for each lua_unlock call
return 0; /// </summary>
}*/ /// <param name = "luaState"></param>
/// Not yet used
public void Close () /*int UnlockCallback(LuaCore.lua_State luaState)
{ {
if (_StatePassed) // Monitor.Exit(luaLock);
return; return 0;
}*/
////// if(luaState != LuaCore.lua_State.Zero)
if (!luaState.IsNull ()) public void Close ()
LuaCore.lua_close (luaState); {
//luaState = LuaCore.lua_State.Zero; <- suggested by Christopher Cebulski http://luaforge.net/forum/forum.php?thread_id = 44593&forum_id = 146 if (_StatePassed)
} return;
////// if(luaState != LuaCore.lua_State.Zero)
if (!luaState.IsNull ()) {
LuaCore.lua_close (luaState);
ObjectTranslatorPool.Instance.Remove (luaState);
}
//luaState = LuaCore.lua_State.Zero; <- suggested by Christopher Cebulski http://luaforge.net/forum/forum.php?thread_id = 44593&forum_id = 146
}
#if MONOTOUCH #if MONOTOUCH
[MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_CFunction))] [MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_CFunction))]
#endif #endif
[System.Runtime.InteropServices.AllowReversePInvokeCalls] [System.Runtime.InteropServices.AllowReversePInvokeCalls]
static int PanicCallback (LuaCore.lua_State luaState) static int PanicCallback (LuaCore.lua_State luaState)
{ {
// string desc = LuaLib.lua_tostring(luaState, 1); // string desc = LuaLib.lua_tostring(luaState, 1);
string reason = string.Format ("unprotected error in call to Lua API ({0})", LuaLib.lua_tostring (luaState, -1)); string reason = string.Format ("unprotected error in call to Lua API ({0})", LuaLib.lua_tostring (luaState, -1));
// lua_tostring(L, -1); // lua_tostring(L, -1);
throw new LuaException (reason); throw new LuaException (reason);
} }
/// <summary> /// <summary>
/// Assuming we have a Lua error string sitting on the stack, throw a C# exception out to the user's app /// Assuming we have a Lua error string sitting on the stack, throw a C# exception out to the user's app
/// </summary> /// </summary>
/// <exception cref = "LuaScriptException">Thrown if the script caused an exception</exception> /// <exception cref = "LuaScriptException">Thrown if the script caused an exception</exception>
private void ThrowExceptionFromError (int oldTop) private void ThrowExceptionFromError (int oldTop)
{ {
object err = translator.getObject (luaState, -1); object err = translator.getObject (luaState, -1);
LuaLib.lua_settop (luaState, oldTop); LuaLib.lua_settop (luaState, oldTop);
// A pre-wrapped exception - just rethrow it (stack trace of InnerException will be preserved) // A pre-wrapped exception - just rethrow it (stack trace of InnerException will be preserved)
var luaEx = err as LuaScriptException; var luaEx = err as LuaScriptException;
if (!luaEx.IsNull ()) if (!luaEx.IsNull ())
throw luaEx; throw luaEx;
// A non-wrapped Lua error (best interpreted as a string) - wrap it and throw it // A non-wrapped Lua error (best interpreted as a string) - wrap it and throw it
if (err.IsNull ()) if (err.IsNull ())
err = "Unknown Lua Error"; err = "Unknown Lua Error";
throw new LuaScriptException (err.ToString (), string.Empty); throw new LuaScriptException (err.ToString (), string.Empty);
} }
/// <summary> /// <summary>
/// Convert C# exceptions into Lua errors /// Convert C# exceptions into Lua errors
/// </summary> /// </summary>
/// <returns>num of things on stack</returns> /// <returns>num of things on stack</returns>
/// <param name = "e">null for no pending exception</param> /// <param name = "e">null for no pending exception</param>
internal int SetPendingException (Exception e) internal int SetPendingException (Exception e)
{ {
var caughtExcept = e; var caughtExcept = e;
if (!caughtExcept.IsNull ()) { if (!caughtExcept.IsNull ()) {
translator.throwError (luaState, caughtExcept); translator.throwError (luaState, caughtExcept);
LuaLib.lua_pushnil (luaState); LuaLib.lua_pushnil (luaState);
return 1; return 1;
} else } else
return 0; return 0;
} }
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
/// <param name = "chunk"></param> /// <param name = "chunk"></param>
/// <param name = "name"></param> /// <param name = "name"></param>
/// <returns></returns> /// <returns></returns>
public LuaFunction LoadString (string chunk, string name) public LuaFunction LoadString (string chunk, string name)
{ {
int oldTop = LuaLib.lua_gettop (luaState); int oldTop = LuaLib.lua_gettop (luaState);
executing = true; executing = true;
try { try {
if (LuaLib.luaL_loadbuffer (luaState, chunk, name) != 0) if (LuaLib.luaL_loadbuffer (luaState, chunk, name) != 0)
ThrowExceptionFromError (oldTop); ThrowExceptionFromError (oldTop);
} finally { } finally {
executing = false; executing = false;
} }
var result = translator.getFunction (luaState, -1); var result = translator.getFunction (luaState, -1);
translator.popValues (luaState, oldTop); translator.popValues (luaState, oldTop);
return result; return result;
} }
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
/// <param name = "fileName"></param> /// <param name = "fileName"></param>
/// <returns></returns> /// <returns></returns>
public LuaFunction LoadFile (string fileName) public LuaFunction LoadFile (string fileName)
{ {
int oldTop = LuaLib.lua_gettop (luaState); int oldTop = LuaLib.lua_gettop (luaState);
if (LuaLib.luaL_loadfile (luaState, fileName) != 0) if (LuaLib.luaL_loadfile (luaState, fileName) != 0)
ThrowExceptionFromError (oldTop); ThrowExceptionFromError (oldTop);
var result = translator.getFunction (luaState, -1); var result = translator.getFunction (luaState, -1);
translator.popValues (luaState, oldTop); translator.popValues (luaState, oldTop);
return result; return result;
} }
/* /*
* Excutes a Lua chunk and returns all the chunk's return * Excutes a Lua chunk and returns all the chunk's return
* values in an array * values in an array
*/ */
public object[] DoString (string chunk) public object[] DoString (string chunk)
{ {
int oldTop = LuaLib.lua_gettop (luaState); int oldTop = LuaLib.lua_gettop (luaState);
if (LuaLib.luaL_loadbuffer (luaState, chunk, "chunk") == 0) { if (LuaLib.luaL_loadbuffer (luaState, chunk, "chunk") == 0) {
executing = true; executing = true;
try { try {
if (LuaLib.lua_pcall (luaState, 0, -1, 0) == 0) if (LuaLib.lua_pcall (luaState, 0, -1, 0) == 0)
return translator.popValues (luaState, oldTop); return translator.popValues (luaState, oldTop);
else else
ThrowExceptionFromError (oldTop); ThrowExceptionFromError (oldTop);
} finally { } finally {
executing = false; executing = false;
} }
} else } else
ThrowExceptionFromError (oldTop); ThrowExceptionFromError (oldTop);
return null; // Never reached - keeps compiler happy return null; // Never reached - keeps compiler happy
} }
/// <summary> /// <summary>
/// Executes a Lua chnk and returns all the chunk's return values in an array. /// Executes a Lua chnk and returns all the chunk's return values in an array.
/// </summary> /// </summary>
/// <param name = "chunk">Chunk to execute</param> /// <param name = "chunk">Chunk to execute</param>
/// <param name = "chunkName">Name to associate with the chunk</param> /// <param name = "chunkName">Name to associate with the chunk</param>
/// <returns></returns> /// <returns></returns>
public object[] DoString (string chunk, string chunkName) public object[] DoString (string chunk, string chunkName)
{ {
int oldTop = LuaLib.lua_gettop (luaState); int oldTop = LuaLib.lua_gettop (luaState);
executing = true; executing = true;
if (LuaLib.luaL_loadbuffer (luaState, chunk, chunkName) == 0) { if (LuaLib.luaL_loadbuffer (luaState, chunk, chunkName) == 0) {
try { try {
if (LuaLib.lua_pcall (luaState, 0, -1, 0) == 0) if (LuaLib.lua_pcall (luaState, 0, -1, 0) == 0)
return translator.popValues (luaState, oldTop); return translator.popValues (luaState, oldTop);
else else
ThrowExceptionFromError (oldTop); ThrowExceptionFromError (oldTop);
} finally { } finally {
executing = false; executing = false;
} }
} else } else
ThrowExceptionFromError (oldTop); ThrowExceptionFromError (oldTop);
return null; // Never reached - keeps compiler happy return null; // Never reached - keeps compiler happy
} }
/* /*
* Excutes a Lua file and returns all the chunk's return * Excutes a Lua file and returns all the chunk's return
* values in an array * values in an array
*/ */
public object[] DoFile (string fileName) public object[] DoFile (string fileName)
{ {
int oldTop = LuaLib.lua_gettop (luaState); int oldTop = LuaLib.lua_gettop (luaState);
if (LuaLib.luaL_loadfile (luaState, fileName) == 0) { if (LuaLib.luaL_loadfile (luaState, fileName) == 0) {
executing = true; executing = true;
try { try {
if (LuaLib.lua_pcall (luaState, 0, -1, 0) == 0) if (LuaLib.lua_pcall (luaState, 0, -1, 0) == 0)
return translator.popValues (luaState, oldTop); return translator.popValues (luaState, oldTop);
else else
ThrowExceptionFromError (oldTop); ThrowExceptionFromError (oldTop);
} finally { } finally {
executing = false; executing = false;
} }
} else } else
ThrowExceptionFromError (oldTop); ThrowExceptionFromError (oldTop);
return null; // Never reached - keeps compiler happy return null; // Never reached - keeps compiler happy
} }
/* /*
* Indexer for global variables from the LuaInterpreter * Indexer for global variables from the LuaInterpreter
* Supports navigation of tables by using . operator * Supports navigation of tables by using . operator
*/ */
public object this [string fullPath] { public object this [string fullPath] {
get { get {
object returnValue = null; object returnValue = null;
int oldTop = LuaLib.lua_gettop (luaState); int oldTop = LuaLib.lua_gettop (luaState);
string[] path = fullPath.Split (new char[] { '.' }); string[] path = fullPath.Split (new char[] { '.' });
LuaLib.lua_getglobal (luaState, path [0]); LuaLib.lua_getglobal (luaState, path [0]);
returnValue = translator.getObject (luaState, -1); returnValue = translator.getObject (luaState, -1);
if (path.Length > 1) { if (path.Length > 1) {
string[] remainingPath = new string[path.Length - 1]; string[] remainingPath = new string[path.Length - 1];
Array.Copy (path, 1, remainingPath, 0, path.Length - 1); Array.Copy (path, 1, remainingPath, 0, path.Length - 1);
returnValue = getObject (remainingPath); returnValue = getObject (remainingPath);
} }
LuaLib.lua_settop (luaState, oldTop); LuaLib.lua_settop (luaState, oldTop);
return returnValue; return returnValue;
} }
set { set {
int oldTop = LuaLib.lua_gettop (luaState); int oldTop = LuaLib.lua_gettop (luaState);
string[] path = fullPath.Split (new char[] { '.' }); string[] path = fullPath.Split (new char[] { '.' });
if (path.Length == 1) { if (path.Length == 1) {
translator.push (luaState, value); translator.push (luaState, value);
LuaLib.lua_setglobal (luaState, fullPath); LuaLib.lua_setglobal (luaState, fullPath);
} else { } else {
LuaLib.lua_getglobal (luaState, path [0]); LuaLib.lua_getglobal (luaState, path [0]);
string[] remainingPath = new string[path.Length - 1]; string[] remainingPath = new string[path.Length - 1];
Array.Copy (path, 1, remainingPath, 0, path.Length - 1); Array.Copy (path, 1, remainingPath, 0, path.Length - 1);
setObject (remainingPath, value); setObject (remainingPath, value);
} }
LuaLib.lua_settop (luaState, oldTop); LuaLib.lua_settop (luaState, oldTop);
// Globals auto-complete // Globals auto-complete
if (value.IsNull ()) { if (value.IsNull ()) {
// Remove now obsolete entries // Remove now obsolete entries
globals.Remove (fullPath); globals.Remove (fullPath);
} else { } else {
// Add new entries // Add new entries
if (!globals.Contains (fullPath)) if (!globals.Contains (fullPath))
registerGlobal (fullPath, value.GetType (), 0); registerGlobal (fullPath, value.GetType (), 0);
} }
} }
} }
#region Globals auto-complete #region Globals auto-complete
/// <summary> /// <summary>
/// Adds an entry to <see cref = "globals"/> (recursivley handles 2 levels of members) /// Adds an entry to <see cref = "globals"/> (recursivley handles 2 levels of members)
/// </summary> /// </summary>
/// <param name = "path">The index accessor path ot the entry</param> /// <param name = "path">The index accessor path ot the entry</param>
/// <param name = "type">The type of the entry</param> /// <param name = "type">The type of the entry</param>
/// <param name = "recursionCounter">How deep have we gone with recursion?</param> /// <param name = "recursionCounter">How deep have we gone with recursion?</param>
private void registerGlobal (string path, Type type, int recursionCounter) private void registerGlobal (string path, Type type, int recursionCounter)
{ {
// If the type is a global method, list it directly // If the type is a global method, list it directly
if (type == typeof(LuaCore.lua_CFunction)) { if (type == typeof(LuaCore.lua_CFunction)) {
// Format for easy method invocation // Format for easy method invocation
globals.Add (path + "("); globals.Add (path + "(");
} }
// If the type is a class or an interface and recursion hasn't been running too long, list the members // If the type is a class or an interface and recursion hasn't been running too long, list the members
else if ((type.IsClass || type.IsInterface) && type != typeof(string) && recursionCounter < 2) { else if ((type.IsClass || type.IsInterface) && type != typeof(string) && recursionCounter < 2) {
#region Methods #region Methods
foreach (var method in type.GetMethods(BindingFlags.Public | BindingFlags.Instance)) { foreach (var method in type.GetMethods(BindingFlags.Public | BindingFlags.Instance)) {
if ( if (
// Check that the LuaHideAttribute and LuaGlobalAttribute were not applied // Check that the LuaHideAttribute and LuaGlobalAttribute were not applied
(method.GetCustomAttributes (typeof(LuaHideAttribute), false).Length == 0) && (method.GetCustomAttributes (typeof(LuaHideAttribute), false).Length == 0) &&
(method.GetCustomAttributes (typeof(LuaGlobalAttribute), false).Length == 0) && (method.GetCustomAttributes (typeof(LuaGlobalAttribute), false).Length == 0) &&
// Exclude some generic .NET methods that wouldn't be very usefull in Lua // Exclude some generic .NET methods that wouldn't be very usefull in Lua
method.Name != "GetType" && method.Name != "GetHashCode" && method.Name != "Equals" && method.Name != "GetType" && method.Name != "GetHashCode" && method.Name != "Equals" &&
method.Name != "ToString" && method.Name != "Clone" && method.Name != "Dispose" && method.Name != "ToString" && method.Name != "Clone" && method.Name != "Dispose" &&
method.Name != "GetEnumerator" && method.Name != "CopyTo" && method.Name != "GetEnumerator" && method.Name != "CopyTo" &&
!method.Name.StartsWith ("get_", StringComparison.Ordinal) && !method.Name.StartsWith ("get_", StringComparison.Ordinal) &&
!method.Name.StartsWith ("set_", StringComparison.Ordinal) && !method.Name.StartsWith ("set_", StringComparison.Ordinal) &&
!method.Name.StartsWith ("add_", StringComparison.Ordinal) && !method.Name.StartsWith ("add_", StringComparison.Ordinal) &&
!method.Name.StartsWith ("remove_", StringComparison.Ordinal)) { !method.Name.StartsWith ("remove_", StringComparison.Ordinal)) {
// Format for easy method invocation // Format for easy method invocation
string command = path + ":" + method.Name + "("; string command = path + ":" + method.Name + "(";
if (method.GetParameters ().Length == 0) if (method.GetParameters ().Length == 0)
command += ")"; command += ")";
globals.Add (command); globals.Add (command);
} }
} }
#endregion #endregion
#region Fields #region Fields
foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.Instance)) { foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.Instance)) {
if ( if (
// Check that the LuaHideAttribute and LuaGlobalAttribute were not applied // Check that the LuaHideAttribute and LuaGlobalAttribute were not applied
(field.GetCustomAttributes (typeof(LuaHideAttribute), false).Length == 0) && (field.GetCustomAttributes (typeof(LuaHideAttribute), false).Length == 0) &&
(field.GetCustomAttributes (typeof(LuaGlobalAttribute), false).Length == 0)) { (field.GetCustomAttributes (typeof(LuaGlobalAttribute), false).Length == 0)) {
// Go into recursion for members // Go into recursion for members
registerGlobal (path + "." + field.Name, field.FieldType, recursionCounter + 1); registerGlobal (path + "." + field.Name, field.FieldType, recursionCounter + 1);
} }
} }
#endregion #endregion
#region Properties #region Properties
foreach (var property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { foreach (var property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance)) {
if ( if (
// Check that the LuaHideAttribute and LuaGlobalAttribute were not applied // Check that the LuaHideAttribute and LuaGlobalAttribute were not applied
(property.GetCustomAttributes (typeof(LuaHideAttribute), false).Length == 0) && (property.GetCustomAttributes (typeof(LuaHideAttribute), false).Length == 0) &&
(property.GetCustomAttributes (typeof(LuaGlobalAttribute), false).Length == 0) (property.GetCustomAttributes (typeof(LuaGlobalAttribute), false).Length == 0)
// Exclude some generic .NET properties that wouldn't be very usefull in Lua // Exclude some generic .NET properties that wouldn't be very usefull in Lua
&& property.Name != "Item") { && property.Name != "Item") {
// Go into recursion for members // Go into recursion for members
registerGlobal (path + "." + property.Name, property.PropertyType, recursionCounter + 1); registerGlobal (path + "." + property.Name, property.PropertyType, recursionCounter + 1);
} }
} }
#endregion #endregion
} else } else
globals.Add (path); // Otherwise simply add the element to the list globals.Add (path); // Otherwise simply add the element to the list
// List will need to be sorted on next access // List will need to be sorted on next access
globalsSorted = false; globalsSorted = false;
} }
#endregion #endregion
/* /*
* Navigates a table in the top of the stack, returning * Navigates a table in the top of the stack, returning
* the value of the specified field * the value of the specified field
*/ */
internal object getObject (string[] remainingPath) internal object getObject (string[] remainingPath)
{ {
object returnValue = null; object returnValue = null;
for (int i = 0; i < remainingPath.Length; i++) { for (int i = 0; i < remainingPath.Length; i++) {
LuaLib.lua_pushstring (luaState, remainingPath [i]); LuaLib.lua_pushstring (luaState, remainingPath [i]);
LuaLib.lua_gettable (luaState, -2); LuaLib.lua_gettable (luaState, -2);
returnValue = translator.getObject (luaState, -1); returnValue = translator.getObject (luaState, -1);
if (returnValue.IsNull ()) if (returnValue.IsNull ())
break; break;
} }
return returnValue; return returnValue;
} }
/* /*
* Gets a numeric global variable * Gets a numeric global variable
*/ */
public double GetNumber (string fullPath) public double GetNumber (string fullPath)
{ {
return (double)this [fullPath]; return (double)this [fullPath];
} }
/* /*
* Gets a string global variable * Gets a string global variable
*/ */
public string GetString (string fullPath) public string GetString (string fullPath)
{ {
return this [fullPath].ToString (); return this [fullPath].ToString ();
} }
/* /*
* Gets a table global variable * Gets a table global variable
*/ */
public LuaTable GetTable (string fullPath) public LuaTable GetTable (string fullPath)
{ {
return (LuaTable)this [fullPath]; return (LuaTable)this [fullPath];
} }
/* /*
* Gets a table global variable as an object implementing * Gets a table global variable as an object implementing
* the interfaceType interface * the interfaceType interface
*/ */
public object GetTable (Type interfaceType, string fullPath) public object GetTable (Type interfaceType, string fullPath)
{ {
return CodeGeneration.Instance.GetClassInstance (interfaceType, GetTable (fullPath)); return CodeGeneration.Instance.GetClassInstance (interfaceType, GetTable (fullPath));
} }
/* /*
* Gets a function global variable * Gets a function global variable
*/ */
public LuaFunction GetFunction (string fullPath) public LuaFunction GetFunction (string fullPath)
{ {
object obj = this [fullPath]; object obj = this [fullPath];
return (obj is LuaCore.lua_CFunction ? new LuaFunction ((LuaCore.lua_CFunction)obj, this) : (LuaFunction)obj); return (obj is LuaCore.lua_CFunction ? new LuaFunction ((LuaCore.lua_CFunction)obj, this) : (LuaFunction)obj);
} }
/* /*
* Register a delegate type to be used to convert Lua funcitions to C# delegates (useful for iOS where there is no dynamic code generation) * Register a delegate type to be used to convert Lua funcitions to C# delegates (useful for iOS where there is no dynamic code generation)
* type delegateType * type delegateType
*/ */
public void RegisterLuaDelegateType (Type delegateType, Type luaDelegateType) public void RegisterLuaDelegateType (Type delegateType, Type luaDelegateType)
{ {
CodeGeneration.Instance.RegisterLuaDelegateType (delegateType, luaDelegateType); CodeGeneration.Instance.RegisterLuaDelegateType (delegateType, luaDelegateType);
} }
public void RegisterLuaClassType (Type klass, Type luaClass) public void RegisterLuaClassType (Type klass, Type luaClass)
{ {
CodeGeneration.Instance.RegisterLuaClassType (klass, luaClass); CodeGeneration.Instance.RegisterLuaClassType (klass, luaClass);
} }
/* /*
* Gets a function global variable as a delegate of * Gets a function global variable as a delegate of
* type delegateType * type delegateType
*/ */
public Delegate GetFunction (Type delegateType, string fullPath) public Delegate GetFunction (Type delegateType, string fullPath)
{ {
return CodeGeneration.Instance.GetDelegate (delegateType, GetFunction (fullPath)); return CodeGeneration.Instance.GetDelegate (delegateType, GetFunction (fullPath));
} }
/* /*
* Calls the object as a function with the provided arguments, * Calls the object as a function with the provided arguments,
* returning the function's returned values inside an array * returning the function's returned values inside an array
*/ */
internal object[] callFunction (object function, object[] args) internal object[] callFunction (object function, object[] args)
{ {
return callFunction (function, args, null); return callFunction (function, args, null);
} }
/* /*
* Calls the object as a function with the provided arguments and * Calls the object as a function with the provided arguments and
* casting returned values to the types in returnTypes before returning * casting returned values to the types in returnTypes before returning
* them in an array * them in an array
*/ */
internal object[] callFunction (object function, object[] args, Type[] returnTypes) internal object[] callFunction (object function, object[] args, Type[] returnTypes)
{ {
int nArgs = 0; int nArgs = 0;
int oldTop = LuaLib.lua_gettop (luaState); int oldTop = LuaLib.lua_gettop (luaState);
if (!LuaLib.lua_checkstack (luaState, args.Length + 6)) if (!LuaLib.lua_checkstack (luaState, args.Length + 6))
throw new LuaException ("Lua stack overflow"); throw new LuaException ("Lua stack overflow");
translator.push (luaState, function); translator.push (luaState, function);
if (!args.IsNull ()) { if (!args.IsNull ()) {
nArgs = args.Length; nArgs = args.Length;
for (int i = 0; i < args.Length; i++) for (int i = 0; i < args.Length; i++)
translator.push (luaState, args [i]); translator.push (luaState, args [i]);
} }
executing = true; executing = true;
try { try {
int error = LuaLib.lua_pcall (luaState, nArgs, -1, 0); int error = LuaLib.lua_pcall (luaState, nArgs, -1, 0);
if (error != 0) if (error != 0)
ThrowExceptionFromError (oldTop); ThrowExceptionFromError (oldTop);
} finally { } finally {
executing = false; executing = false;
} }
return !returnTypes.IsNull () ? translator.popValues (luaState, oldTop, returnTypes) : translator.popValues (luaState, oldTop); return !returnTypes.IsNull () ? translator.popValues (luaState, oldTop, returnTypes) : translator.popValues (luaState, oldTop);
} }
/* /*
* Navigates a table to set the value of one of its fields * Navigates a table to set the value of one of its fields
*/ */
internal void setObject (string[] remainingPath, object val) internal void setObject (string[] remainingPath, object val)
{ {
for (int i = 0; i < remainingPath.Length-1; i++) { for (int i = 0; i < remainingPath.Length-1; i++) {
LuaLib.lua_pushstring (luaState, remainingPath [i]); LuaLib.lua_pushstring (luaState, remainingPath [i]);
LuaLib.lua_gettable (luaState, -2); LuaLib.lua_gettable (luaState, -2);
} }
LuaLib.lua_pushstring (luaState, remainingPath [remainingPath.Length - 1]); LuaLib.lua_pushstring (luaState, remainingPath [remainingPath.Length - 1]);
translator.push (luaState, val); translator.push (luaState, val);
LuaLib.lua_settable (luaState, -3); LuaLib.lua_settable (luaState, -3);
} }
/* /*
* Creates a new table as a global variable or as a field * Creates a new table as a global variable or as a field
* inside an existing table * inside an existing table
*/ */
public void NewTable (string fullPath) public void NewTable (string fullPath)
{ {
string[] path = fullPath.Split (new char[] { '.' }); string[] path = fullPath.Split (new char[] { '.' });
int oldTop = LuaLib.lua_gettop (luaState); int oldTop = LuaLib.lua_gettop (luaState);
if (path.Length == 1) { if (path.Length == 1) {
LuaLib.lua_newtable (luaState); LuaLib.lua_newtable (luaState);
LuaLib.lua_setglobal (luaState, fullPath); LuaLib.lua_setglobal (luaState, fullPath);
} else { } else {
LuaLib.lua_getglobal (luaState, path [0]); LuaLib.lua_getglobal (luaState, path [0]);
for (int i = 1; i < path.Length-1; i++) { for (int i = 1; i < path.Length-1; i++) {
LuaLib.lua_pushstring (luaState, path [i]); LuaLib.lua_pushstring (luaState, path [i]);
LuaLib.lua_gettable (luaState, -2); LuaLib.lua_gettable (luaState, -2);
} }
LuaLib.lua_pushstring (luaState, path [path.Length - 1]); LuaLib.lua_pushstring (luaState, path [path.Length - 1]);
LuaLib.lua_newtable (luaState); LuaLib.lua_newtable (luaState);
LuaLib.lua_settable (luaState, -3); LuaLib.lua_settable (luaState, -3);
} }
LuaLib.lua_settop (luaState, oldTop); LuaLib.lua_settop (luaState, oldTop);
} }
public ListDictionary GetTableDict (LuaTable table) public ListDictionary GetTableDict (LuaTable table)
{ {
var dict = new ListDictionary (); var dict = new ListDictionary ();
int oldTop = LuaLib.lua_gettop (luaState); int oldTop = LuaLib.lua_gettop (luaState);
translator.push (luaState, table); translator.push (luaState, table);
LuaLib.lua_pushnil (luaState); LuaLib.lua_pushnil (luaState);
while (LuaLib.lua_next(luaState, -2) != 0) { while (LuaLib.lua_next(luaState, -2) != 0) {
dict [translator.getObject (luaState, -2)] = translator.getObject (luaState, -1); dict [translator.getObject (luaState, -2)] = translator.getObject (luaState, -1);
LuaLib.lua_settop (luaState, -2); LuaLib.lua_settop (luaState, -2);
} }
LuaLib.lua_settop (luaState, oldTop); LuaLib.lua_settop (luaState, oldTop);
return dict; return dict;
} }
/* /*
* Lets go of a previously allocated reference to a table, function * Lets go of a previously allocated reference to a table, function
* or userdata * or userdata
*/ */
#region lua debug functions #region lua debug functions
/// <summary> /// <summary>
/// Activates the debug hook /// Activates the debug hook
/// </summary> /// </summary>
/// <param name = "mask">Mask</param> /// <param name = "mask">Mask</param>
/// <param name = "count">Count</param> /// <param name = "count">Count</param>
/// <returns>see lua docs. -1 if hook is already set</returns> /// <returns>see lua docs. -1 if hook is already set</returns>
/// <author>Reinhard Ostermeier</author> /// <author>Reinhard Ostermeier</author>
public int SetDebugHook (EventMasks mask, int count) public int SetDebugHook (EventMasks mask, int count)
{ {
if (hookCallback.IsNull ()) { if (hookCallback.IsNull ()) {
hookCallback = new LuaCore.lua_Hook (DebugHookCallback); hookCallback = new LuaCore.lua_Hook (Lua.DebugHookCallback);
return LuaCore.lua_sethook (luaState, hookCallback, (int)mask, count); return LuaCore.lua_sethook (luaState, hookCallback, (int)mask, count);
} }
return -1; return -1;
} }
/// <summary> /// <summary>
/// Removes the debug hook /// Removes the debug hook
/// </summary> /// </summary>
/// <returns>see lua docs</returns> /// <returns>see lua docs</returns>
/// <author>Reinhard Ostermeier</author> /// <author>Reinhard Ostermeier</author>
public int RemoveDebugHook () public int RemoveDebugHook ()
{ {
hookCallback = null; hookCallback = null;
return LuaCore.lua_sethook (luaState, null, 0, 0); return LuaCore.lua_sethook (luaState, null, 0, 0);
} }
/// <summary> /// <summary>
/// Gets the hook mask. /// Gets the hook mask.
/// </summary> /// </summary>
/// <returns>hook mask</returns> /// <returns>hook mask</returns>
/// <author>Reinhard Ostermeier</author> /// <author>Reinhard Ostermeier</author>
public EventMasks GetHookMask () public EventMasks GetHookMask ()
{ {
return (EventMasks)LuaCore.lua_gethookmask (luaState); return (EventMasks)LuaCore.lua_gethookmask (luaState);
} }
/// <summary> /// <summary>
/// Gets the hook count /// Gets the hook count
/// </summary> /// </summary>
/// <returns>see lua docs</returns> /// <returns>see lua docs</returns>
/// <author>Reinhard Ostermeier</author> /// <author>Reinhard Ostermeier</author>
public int GetHookCount () public int GetHookCount ()
{ {
return LuaCore.lua_gethookcount (luaState); return LuaCore.lua_gethookcount (luaState);
} }
/// <summary> /// <summary>
/// Gets the stack entry on a given level /// Gets the stack entry on a given level
/// </summary> /// </summary>
/// <param name = "level">level</param> /// <param name = "level">level</param>
/// <param name = "luaDebug">lua debug structure</param> /// <param name = "luaDebug">lua debug structure</param>
/// <returns>Returns true if level was allowed, false if level was invalid.</returns> /// <returns>Returns true if level was allowed, false if level was invalid.</returns>
/// <author>Reinhard Ostermeier</author> /// <author>Reinhard Ostermeier</author>
/*public bool GetStack(int level, out LuaCore.lua_Debug luaDebug) /*public bool GetStack(int level, out LuaCore.lua_Debug luaDebug)
{ {
luaDebug = new LuaDebug(); luaDebug = new LuaDebug();
LuaCore.lua_State ld = System.Runtime.InteropServices.Marshal.AllocHGlobal(System.Runtime.InteropServices.Marshal.SizeOf(luaDebug)); LuaCore.lua_State ld = System.Runtime.InteropServices.Marshal.AllocHGlobal(System.Runtime.InteropServices.Marshal.SizeOf(luaDebug));
System.Runtime.InteropServices.Marshal.StructureToPtr(luaDebug, ld, false); System.Runtime.InteropServices.Marshal.StructureToPtr(luaDebug, ld, false);
try try
{ {
return LuaLib.lua_getstack(luaState, level, luaDebug) != 0; return LuaLib.lua_getstack(luaState, level, luaDebug) != 0;
} }
finally finally
{ {
luaDebug = (LuaDebug)System.Runtime.InteropServices.Marshal.PtrToStructure(ld, typeof(LuaDebug)); luaDebug = (LuaDebug)System.Runtime.InteropServices.Marshal.PtrToStructure(ld, typeof(LuaDebug));
System.Runtime.InteropServices.Marshal.FreeHGlobal(ld); System.Runtime.InteropServices.Marshal.FreeHGlobal(ld);
} }
}*/ }*/
/// <summary> /// <summary>
/// Gets info (see lua docs) /// Gets info (see lua docs)
/// </summary> /// </summary>
/// <param name = "what">what (see lua docs)</param> /// <param name = "what">what (see lua docs)</param>
/// <param name = "luaDebug">lua debug structure</param> /// <param name = "luaDebug">lua debug structure</param>
/// <returns>see lua docs</returns> /// <returns>see lua docs</returns>
/// <author>Reinhard Ostermeier</author> /// <author>Reinhard Ostermeier</author>
/*public int GetInfo(String what, ref LuaCore.lua_Debug luaDebug) /*public int GetInfo(String what, ref LuaCore.lua_Debug luaDebug)
{ {
LuaCore.lua_State ld = System.Runtime.InteropServices.Marshal.AllocHGlobal(System.Runtime.InteropServices.Marshal.SizeOf(luaDebug)); LuaCore.lua_State ld = System.Runtime.InteropServices.Marshal.AllocHGlobal(System.Runtime.InteropServices.Marshal.SizeOf(luaDebug));
System.Runtime.InteropServices.Marshal.StructureToPtr(luaDebug, ld, false); System.Runtime.InteropServices.Marshal.StructureToPtr(luaDebug, ld, false);
try try
{ {
return LuaLib.lua_getinfo(luaState, what, ld); return LuaLib.lua_getinfo(luaState, what, ld);
} }
finally finally
{ {
luaDebug = (LuaDebug)System.Runtime.InteropServices.Marshal.PtrToStructure(ld, typeof(LuaDebug)); luaDebug = (LuaDebug)System.Runtime.InteropServices.Marshal.PtrToStructure(ld, typeof(LuaDebug));
System.Runtime.InteropServices.Marshal.FreeHGlobal(ld); System.Runtime.InteropServices.Marshal.FreeHGlobal(ld);
} }
}*/ }*/
/// <summary> /// <summary>
/// Gets local (see lua docs) /// Gets local (see lua docs)
/// </summary> /// </summary>
/// <param name = "luaDebug">lua debug structure</param> /// <param name = "luaDebug">lua debug structure</param>
/// <param name = "n">see lua docs</param> /// <param name = "n">see lua docs</param>
/// <returns>see lua docs</returns> /// <returns>see lua docs</returns>
/// <author>Reinhard Ostermeier</author> /// <author>Reinhard Ostermeier</author>
public string GetLocal (LuaCore.lua_Debug luaDebug, int n) public string GetLocal (LuaCore.lua_Debug luaDebug, int n)
{ {
return LuaCore.lua_getlocal (luaState, luaDebug, n).ToString (); return LuaCore.lua_getlocal (luaState, luaDebug, n).ToString ();
} }
/// <summary> /// <summary>
/// Sets local (see lua docs) /// Sets local (see lua docs)
/// </summary> /// </summary>
/// <param name = "luaDebug">lua debug structure</param> /// <param name = "luaDebug">lua debug structure</param>
/// <param name = "n">see lua docs</param> /// <param name = "n">see lua docs</param>
/// <returns>see lua docs</returns> /// <returns>see lua docs</returns>
/// <author>Reinhard Ostermeier</author> /// <author>Reinhard Ostermeier</author>
public string SetLocal (LuaCore.lua_Debug luaDebug, int n) public string SetLocal (LuaCore.lua_Debug luaDebug, int n)
{ {
return LuaCore.lua_setlocal (luaState, luaDebug, n).ToString (); return LuaCore.lua_setlocal (luaState, luaDebug, n).ToString ();
} }
/// <summary> /// <summary>
/// Gets up value (see lua docs) /// Gets up value (see lua docs)
/// </summary> /// </summary>
/// <param name = "funcindex">see lua docs</param> /// <param name = "funcindex">see lua docs</param>
/// <param name = "n">see lua docs</param> /// <param name = "n">see lua docs</param>
/// <returns>see lua docs</returns> /// <returns>see lua docs</returns>
/// <author>Reinhard Ostermeier</author> /// <author>Reinhard Ostermeier</author>
public string GetUpValue (int funcindex, int n) public string GetUpValue (int funcindex, int n)
{ {
return LuaCore.lua_getupvalue (luaState, funcindex, n).ToString (); return LuaCore.lua_getupvalue (luaState, funcindex, n).ToString ();
} }
/// <summary> /// <summary>
/// Sets up value (see lua docs) /// Sets up value (see lua docs)
/// </summary> /// </summary>
/// <param name = "funcindex">see lua docs</param> /// <param name = "funcindex">see lua docs</param>
/// <param name = "n">see lua docs</param> /// <param name = "n">see lua docs</param>
/// <returns>see lua docs</returns> /// <returns>see lua docs</returns>
/// <author>Reinhard Ostermeier</author> /// <author>Reinhard Ostermeier</author>
public string SetUpValue (int funcindex, int n) public string SetUpValue (int funcindex, int n)
{ {
return LuaCore.lua_setupvalue (luaState, funcindex, n).ToString (); return LuaCore.lua_setupvalue (luaState, funcindex, n).ToString ();
} }
/// <summary> /// <summary>
/// Delegate that is called on lua hook callback /// Delegate that is called on lua hook callback
/// </summary> /// </summary>
/// <param name = "luaState">lua state</param> /// <param name = "luaState">lua state</param>
/// <param name = "luaDebug">Pointer to LuaDebug (lua_debug) structure</param> /// <param name = "luaDebug">Pointer to LuaDebug (lua_debug) structure</param>
/// <author>Reinhard Ostermeier</author> /// <author>Reinhard Ostermeier</author>
/// ///
#if MONOTOUCH #if MONOTOUCH
[MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_Hook))] [MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_Hook))]
#endif #endif
[System.Runtime.InteropServices.AllowReversePInvokeCalls] [System.Runtime.InteropServices.AllowReversePInvokeCalls]
private void DebugHookCallback (LuaCore.lua_State luaState, LuaCore.lua_Debug luaDebug) private static void DebugHookCallback (LuaCore.lua_State luaState, LuaCore.lua_Debug luaDebug)
{ {
try { var translator = ObjectTranslatorPool.Instance.Find (luaState);
var temp = DebugHook; var lua = translator.Interpreter;
if (!temp.IsNull ()) lua.DebugHookCallbackInternal (luaState, luaDebug);
temp (this, new DebugHookEventArgs (luaDebug)); }
} catch (Exception ex) {
OnHookException (new HookExceptionEventArgs (ex)); private void DebugHookCallbackInternal (LuaCore.lua_State luaState, LuaCore.lua_Debug luaDebug)
} {
} try {
var temp = DebugHook;
private void OnHookException (HookExceptionEventArgs e)
{ if (!temp.IsNull ())
var temp = HookException; temp (this, new DebugHookEventArgs (luaDebug));
if (!temp.IsNull ()) } catch (Exception ex) {
temp (this, e); OnHookException (new HookExceptionEventArgs (ex));
} }
}
/// <summary>
/// Pops a value from the lua stack. private void OnHookException (HookExceptionEventArgs e)
/// </summary> {
/// <returns>Returns the top value from the lua stack.</returns> var temp = HookException;
/// <author>Reinhard Ostermeier</author> if (!temp.IsNull ())
public object Pop () temp (this, e);
{ }
int top = LuaLib.lua_gettop (luaState);
return translator.popValues (luaState, top - 1) [0]; /// <summary>
} /// Pops a value from the lua stack.
/// </summary>
/// <summary> /// <returns>Returns the top value from the lua stack.</returns>
/// Pushes a value onto the lua stack. /// <author>Reinhard Ostermeier</author>
/// </summary> public object Pop ()
/// <param name = "value">Value to push.</param> {
/// <author>Reinhard Ostermeier</author> int top = LuaLib.lua_gettop (luaState);
public void Push (object value) return translator.popValues (luaState, top - 1) [0];
{ }
translator.push (luaState, value);
} /// <summary>
#endregion /// Pushes a value onto the lua stack.
/// </summary>
internal void dispose (int reference) /// <param name = "value">Value to push.</param>
{ /// <author>Reinhard Ostermeier</author>
if (!luaState.IsNull ()) //Fix submitted by Qingrui Li public void Push (object value)
LuaLib.lua_unref (luaState, reference); {
} translator.push (luaState, value);
}
/* #endregion
* Gets a field of the table corresponding to the provided reference
* using rawget (do not use metatables) internal void dispose (int reference)
*/ {
internal object rawGetObject (int reference, string field) if (!luaState.IsNull ()) //Fix submitted by Qingrui Li
{ LuaLib.lua_unref (luaState, reference);
int oldTop = LuaLib.lua_gettop (luaState); }
LuaLib.lua_getref (luaState, reference);
LuaLib.lua_pushstring (luaState, field); /*
LuaLib.lua_rawget (luaState, -2); * Gets a field of the table corresponding to the provided reference
object obj = translator.getObject (luaState, -1); * using rawget (do not use metatables)
LuaLib.lua_settop (luaState, oldTop); */
return obj; internal object rawGetObject (int reference, string field)
} {
int oldTop = LuaLib.lua_gettop (luaState);
/* LuaLib.lua_getref (luaState, reference);
* Gets a field of the table or userdata corresponding to the provided reference LuaLib.lua_pushstring (luaState, field);
*/ LuaLib.lua_rawget (luaState, -2);
internal object getObject (int reference, string field) object obj = translator.getObject (luaState, -1);
{ LuaLib.lua_settop (luaState, oldTop);
int oldTop = LuaLib.lua_gettop (luaState); return obj;
LuaLib.lua_getref (luaState, reference); }
object returnValue = getObject (field.Split (new char[] {'.'}));
LuaLib.lua_settop (luaState, oldTop); /*
return returnValue; * Gets a field of the table or userdata corresponding to the provided reference
} */
internal object getObject (int reference, string field)
/* {
* Gets a numeric field of the table or userdata corresponding the the provided reference int oldTop = LuaLib.lua_gettop (luaState);
*/ LuaLib.lua_getref (luaState, reference);
object returnValue = getObject (field.Split (new char[] {'.'}));
internal object getObject (int reference, object field) LuaLib.lua_settop (luaState, oldTop);
{ return returnValue;
int oldTop = LuaLib.lua_gettop (luaState); }
LuaLib.lua_getref (luaState, reference);
translator.push (luaState, field); /*
LuaLib.lua_gettable (luaState, -2); * Gets a numeric field of the table or userdata corresponding the the provided reference
object returnValue = translator.getObject (luaState, -1); */
LuaLib.lua_settop (luaState, oldTop);
return returnValue; internal object getObject (int reference, object field)
} {
int oldTop = LuaLib.lua_gettop (luaState);
/* LuaLib.lua_getref (luaState, reference);
* Sets a field of the table or userdata corresponding the the provided reference translator.push (luaState, field);
* to the provided value LuaLib.lua_gettable (luaState, -2);
*/ object returnValue = translator.getObject (luaState, -1);
internal void setObject (int reference, string field, object val) LuaLib.lua_settop (luaState, oldTop);
{ return returnValue;
int oldTop = LuaLib.lua_gettop (luaState); }
LuaLib.lua_getref (luaState, reference);
setObject (field.Split (new char[] {'.'}), val); /*
LuaLib.lua_settop (luaState, oldTop); * Sets a field of the table or userdata corresponding the the provided reference
} * to the provided value
*/
/* internal void setObject (int reference, string field, object val)
* Sets a numeric field of the table or userdata corresponding the the provided reference {
* to the provided value int oldTop = LuaLib.lua_gettop (luaState);
*/ LuaLib.lua_getref (luaState, reference);
internal void setObject (int reference, object field, object val) setObject (field.Split (new char[] {'.'}), val);
{ LuaLib.lua_settop (luaState, oldTop);
int oldTop = LuaLib.lua_gettop (luaState); }
LuaLib.lua_getref (luaState, reference);
translator.push (luaState, field); /*
translator.push (luaState, val); * Sets a numeric field of the table or userdata corresponding the the provided reference
LuaLib.lua_settable (luaState, -3); * to the provided value
LuaLib.lua_settop (luaState, oldTop); */
} internal void setObject (int reference, object field, object val)
{
/* int oldTop = LuaLib.lua_gettop (luaState);
* Registers an object's method as a Lua function (global or table field) LuaLib.lua_getref (luaState, reference);
* The method may have any signature translator.push (luaState, field);
*/ translator.push (luaState, val);
public LuaFunction RegisterFunction (string path, object target, MethodBase function /*MethodInfo function*/) //CP: Fix for struct constructor by Alexander Kappner (link: http://luaforge.net/forum/forum.php?thread_id = 2859&forum_id = 145) LuaLib.lua_settable (luaState, -3);
{ LuaLib.lua_settop (luaState, oldTop);
// We leave nothing on the stack when we are done }
int oldTop = LuaLib.lua_gettop (luaState);
var wrapper = new LuaMethodWrapper (translator, target, function.DeclaringType, function); /*
translator.push (luaState, new LuaCore.lua_CFunction (wrapper.invokeFunction)); * Registers an object's method as a Lua function (global or table field)
this [path] = translator.getObject (luaState, -1); * The method may have any signature
var f = GetFunction (path); */
LuaLib.lua_settop (luaState, oldTop); public LuaFunction RegisterFunction (string path, object target, MethodBase function /*MethodInfo function*/) //CP: Fix for struct constructor by Alexander Kappner (link: http://luaforge.net/forum/forum.php?thread_id = 2859&forum_id = 145)
return f; {
} // We leave nothing on the stack when we are done
int oldTop = LuaLib.lua_gettop (luaState);
/* var wrapper = new LuaMethodWrapper (translator, target, function.DeclaringType, function);
* Compares the two values referenced by ref1 and ref2 for equality translator.push (luaState, new LuaCore.lua_CFunction (wrapper.invokeFunction));
*/ this [path] = translator.getObject (luaState, -1);
internal bool compareRef (int ref1, int ref2) var f = GetFunction (path);
{ LuaLib.lua_settop (luaState, oldTop);
int top = LuaLib.lua_gettop (luaState); return f;
LuaLib.lua_getref (luaState, ref1); }
LuaLib.lua_getref (luaState, ref2);
int equal = LuaLib.lua_equal (luaState, -1, -2); /*
LuaLib.lua_settop (luaState, top); * Compares the two values referenced by ref1 and ref2 for equality
return (equal != 0); */
} internal bool compareRef (int ref1, int ref2)
{
internal void pushCSFunction (LuaCore.lua_CFunction function) int top = LuaLib.lua_gettop (luaState);
{ LuaLib.lua_getref (luaState, ref1);
translator.pushFunction (luaState, function); LuaLib.lua_getref (luaState, ref2);
} int equal = LuaLib.lua_equal (luaState, -1, -2);
LuaLib.lua_settop (luaState, top);
#region IDisposable Members return (equal != 0);
public virtual void Dispose () }
{
if (!translator.IsNull ()) { internal void pushCSFunction (LuaCore.lua_CFunction function)
translator.pendingEvents.Dispose (); {
translator = null; translator.pushFunction (luaState, function);
} }
this.Close (); #region IDisposable Members
GC.Collect (); public virtual void Dispose ()
GC.WaitForPendingFinalizers (); {
} if (!translator.IsNull ()) {
#endregion translator.pendingEvents.Dispose ();
} translator = null;
}
this.Close ();
GC.Collect ();
GC.WaitForPendingFinalizers ();
}
#endregion
}
} }
\ No newline at end of file
/* /*
* This file is part of LuaInterface. * This file is part of LuaInterface.
* *
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz. * Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/> * Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*/ */
using System; using System;
using System.Text; using System.Text;
using System.Collections.Generic; using System.Collections.Generic;
namespace LuaInterface namespace LuaInterface
{ {
using LuaCore = KeraLua.Lua; #if USE_KOPILUA
using LuaCore = KopiLua.Lua;
public class LuaFunction : LuaBase #else
{ using LuaCore = KeraLua.Lua;
internal LuaCore.lua_CFunction function; #endif
public LuaFunction (int reference, Lua interpreter) public class LuaFunction : LuaBase
{ {
_Reference = reference; internal LuaCore.lua_CFunction function;
this.function = null;
_Interpreter = interpreter; public LuaFunction (int reference, Lua interpreter)
} {
_Reference = reference;
public LuaFunction (LuaCore.lua_CFunction function, Lua interpreter) this.function = null;
{ _Interpreter = interpreter;
_Reference = 0; }
this.function = function;
_Interpreter = interpreter; public LuaFunction (LuaCore.lua_CFunction function, Lua interpreter)
} {
_Reference = 0;
/* this.function = function;
* Calls the function casting return values to the types _Interpreter = interpreter;
* in returnTypes }
*/
internal object[] call (object[] args, Type[] returnTypes) /*
{ * Calls the function casting return values to the types
return _Interpreter.callFunction (this, args, returnTypes); * in returnTypes
} */
internal object[] call (object[] args, Type[] returnTypes)
/* {
* Calls the function and returns its return values inside return _Interpreter.callFunction (this, args, returnTypes);
* an array }
*/
public object[] Call (params object[] args) /*
{ * Calls the function and returns its return values inside
return _Interpreter.callFunction (this, args); * an array
} */
public object[] Call (params object[] args)
/* {
* Pushes the function into the Lua stack return _Interpreter.callFunction (this, args);
*/ }
internal void push (LuaCore.lua_State luaState)
{ /*
if (_Reference != 0) * Pushes the function into the Lua stack
LuaLib.lua_getref (luaState, _Reference); */
else internal void push (LuaCore.lua_State luaState)
_Interpreter.pushCSFunction (function); {
} if (_Reference != 0)
LuaLib.lua_getref (luaState, _Reference);
public override string ToString () else
{ _Interpreter.pushCSFunction (function);
return "function"; }
}
public override string ToString ()
public override bool Equals (object o) {
{ return "function";
if (o is LuaFunction) { }
var l = (LuaFunction)o;
public override bool Equals (object o)
if (this._Reference != 0 && l._Reference != 0) {
return _Interpreter.compareRef (l._Reference, this._Reference); if (o is LuaFunction) {
else var l = (LuaFunction)o;
return this.function == l.function;
} else if (this._Reference != 0 && l._Reference != 0)
return false; return _Interpreter.compareRef (l._Reference, this._Reference);
} else
return this.function == l.function;
public override int GetHashCode () } else
{ return false;
return _Reference != 0 ? _Reference : function.GetHashCode (); }
}
} public override int GetHashCode ()
{
return _Reference != 0 ? _Reference : function.GetHashCode ();
}
}
} }
\ No newline at end of file
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
<DebugType>full</DebugType> <DebugType>full</DebugType>
<Optimize>False</Optimize> <Optimize>False</Optimize>
<OutputPath>bin\Debug</OutputPath> <OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;MONOTOUCH</DefineConstants> <DefineConstants>DEBUG;MONOTOUCH;</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<ConsolePause>False</ConsolePause> <ConsolePause>False</ConsolePause>
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<ConsolePause>False</ConsolePause> <ConsolePause>False</ConsolePause>
<DefineConstants>MONOTOUCH</DefineConstants> <DefineConstants>MONOTOUCH;</DefineConstants>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <Reference Include="System" />
...@@ -91,6 +91,7 @@ ...@@ -91,6 +91,7 @@
<Compile Include="Metatables.cs" /> <Compile Include="Metatables.cs" />
<Compile Include="ObjectTranslator.cs" /> <Compile Include="ObjectTranslator.cs" />
<Compile Include="ProxyType.cs" /> <Compile Include="ProxyType.cs" />
<Compile Include="ObjectTranslatorPool.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\KeraLua\KeraLua.iOS.csproj"> <ProjectReference Include="..\KeraLua\KeraLua.iOS.csproj">
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
<AssemblyName>LuaInterface</AssemblyName> <AssemblyName>LuaInterface</AssemblyName>
<ReleaseVersion>2.x</ReleaseVersion> <ReleaseVersion>2.x</ReleaseVersion>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion> <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<TargetFrameworkProfile />
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>True</DebugSymbols> <DebugSymbols>True</DebugSymbols>
...@@ -79,6 +78,7 @@ ...@@ -79,6 +78,7 @@
<Compile Include="LuaLib\GCOptions.cs" /> <Compile Include="LuaLib\GCOptions.cs" />
<Compile Include="LuaLib\LuaLib.cs" /> <Compile Include="LuaLib\LuaLib.cs" />
<Compile Include="Config\LuaInterfaceConfig.cs" /> <Compile Include="Config\LuaInterfaceConfig.cs" />
<Compile Include="ObjectTranslatorPool.cs" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
...@@ -90,7 +90,7 @@ ...@@ -90,7 +90,7 @@
--> -->
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\KeraLua\KeraLua.csproj"> <ProjectReference Include="..\KeraLua\KeraLua.csproj">
<Project>{47153754-10f5-44d8-b578-f5a32b69061a}</Project> <Project>{47153754-10F5-44D8-B578-F5A32B69061A}</Project>
<Name>KeraLua</Name> <Name>KeraLua</Name>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\KopiLua\KopiLua.csproj"> <ProjectReference Include="..\KopiLua\KopiLua.csproj">
......
/* /*
* This file is part of LuaInterface. * This file is part of LuaInterface.
* *
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz. * Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2009 Joshua Simmons <simmons.44@gmail.com> * Copyright (C) 2009 Joshua Simmons <simmons.44@gmail.com>
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/> * Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*/ */
using System; using System;
using System.IO; using System.IO;
using LuaInterface.Extensions; using LuaInterface.Extensions;
namespace LuaInterface namespace LuaInterface
{ {
using LuaCore = KeraLua.Lua; #if USE_KOPILUA
using LuaCore = KopiLua.Lua;
public class LuaLib #else
{ using LuaCore = KeraLua.Lua;
// steffenj: BEGIN additional Lua API functions new in Lua 5.1 #endif
public static int lua_gc (LuaCore.lua_State luaState, GCOptions what, int data)
{ public class LuaLib
return LuaCore.lua_gc (luaState, (int)what, data); {
} // steffenj: BEGIN additional Lua API functions new in Lua 5.1
public static int lua_gc (LuaCore.lua_State luaState, GCOptions what, int data)
public static string lua_typename (LuaCore.lua_State luaState, LuaTypes type) {
{ return LuaCore.lua_gc (luaState, (int)what, data);
return LuaCore.lua_typename (luaState, (int)type).ToString (); }
}
public static string lua_typename (LuaCore.lua_State luaState, LuaTypes type)
public static string luaL_typename (LuaCore.lua_State luaState, int stackPos) {
{ return LuaCore.lua_typename (luaState, (int)type).ToString ();
return lua_typename (luaState, lua_type (luaState, stackPos)); }
}
public static string luaL_typename (LuaCore.lua_State luaState, int stackPos)
public static void luaL_error (LuaCore.lua_State luaState, string message) {
{ return lua_typename (luaState, lua_type (luaState, stackPos));
LuaCore.luaL_error (luaState, message); }
}
public static void luaL_error (LuaCore.lua_State luaState, string message)
public static void luaL_where (LuaCore.lua_State luaState, int level) {
{ LuaCore.luaL_error (luaState, message);
LuaCore.luaL_where (luaState, level); }
}
public static void luaL_where (LuaCore.lua_State luaState, int level)
// steffenj: BEGIN Lua 5.1.1 API change (lua_open replaced by luaL_newstate) {
public static LuaCore.lua_State luaL_newstate () LuaCore.luaL_where (luaState, level);
{ }
return LuaCore.luaL_newstate ();
} // steffenj: BEGIN Lua 5.1.1 API change (lua_open replaced by luaL_newstate)
public static LuaCore.lua_State luaL_newstate ()
// steffenj: BEGIN Lua 5.1.1 API change (new function luaL_openlibs) {
public static void luaL_openlibs (LuaCore.lua_State luaState) return LuaCore.luaL_newstate ();
{ }
LuaCore.luaL_openlibs (luaState);
} // steffenj: BEGIN Lua 5.1.1 API change (new function luaL_openlibs)
public static void luaL_openlibs (LuaCore.lua_State luaState)
// steffenj: END Lua 5.1.1 API change (lua_strlen is now lua_objlen) {
// steffenj: BEGIN Lua 5.1.1 API change (lua_dostring is now a macro luaL_dostring) LuaCore.luaL_openlibs (luaState);
public static int luaL_loadstring (LuaCore.lua_State luaState, string chunk) }
{
return LuaCore.luaL_loadstring (luaState, chunk); // steffenj: END Lua 5.1.1 API change (lua_strlen is now lua_objlen)
} // steffenj: BEGIN Lua 5.1.1 API change (lua_dostring is now a macro luaL_dostring)
public static int luaL_loadstring (LuaCore.lua_State luaState, string chunk)
public static int luaL_dostring (LuaCore.lua_State luaState, string chunk) {
{ return LuaCore.luaL_loadstring (luaState, chunk);
int result = luaL_loadstring (luaState, chunk); }
if (result != 0)
return result; public static int luaL_dostring (LuaCore.lua_State luaState, string chunk)
{
return lua_pcall (luaState, 0, -1, 0); int result = luaL_loadstring (luaState, chunk);
} if (result != 0)
return result;
/// <summary>DEPRECATED - use luaL_dostring(LuaCore.lua_State luaState, string chunk) instead!</summary>
public static int lua_dostring (LuaCore.lua_State luaState, string chunk) return lua_pcall (luaState, 0, -1, 0);
{ }
return luaL_dostring (luaState, chunk);
} /// <summary>DEPRECATED - use luaL_dostring(LuaCore.lua_State luaState, string chunk) instead!</summary>
public static int lua_dostring (LuaCore.lua_State luaState, string chunk)
// steffenj: END Lua 5.1.1 API change (lua_dostring is now a macro luaL_dostring) {
// steffenj: BEGIN Lua 5.1.1 API change (lua_newtable is gone, lua_createtable is new) return luaL_dostring (luaState, chunk);
public static void lua_createtable (LuaCore.lua_State luaState, int narr, int nrec) }
{
LuaCore.lua_createtable (luaState, narr, nrec); // steffenj: END Lua 5.1.1 API change (lua_dostring is now a macro luaL_dostring)
} // steffenj: BEGIN Lua 5.1.1 API change (lua_newtable is gone, lua_createtable is new)
public static void lua_createtable (LuaCore.lua_State luaState, int narr, int nrec)
public static void lua_newtable (LuaCore.lua_State luaState) {
{ LuaCore.lua_createtable (luaState, narr, nrec);
lua_createtable (luaState, 0, 0); }
}
public static void lua_newtable (LuaCore.lua_State luaState)
// steffenj: END Lua 5.1.1 API change (lua_newtable is gone, lua_createtable is new) {
// steffenj: BEGIN Lua 5.1.1 API change (lua_dofile now in LuaLib as luaL_dofile macro) lua_createtable (luaState, 0, 0);
public static int luaL_dofile (LuaCore.lua_State luaState, string fileName) }
{
int result = LuaCore.luaL_loadfile (luaState, fileName); // steffenj: END Lua 5.1.1 API change (lua_newtable is gone, lua_createtable is new)
if (result != 0) // steffenj: BEGIN Lua 5.1.1 API change (lua_dofile now in LuaLib as luaL_dofile macro)
return result; public static int luaL_dofile (LuaCore.lua_State luaState, string fileName)
{
return LuaCore.lua_pcall (luaState, 0, -1, 0); int result = LuaCore.luaL_loadfile (luaState, fileName);
} if (result != 0)
return result;
// steffenj: END Lua 5.1.1 API change (lua_dofile now in LuaLib as luaL_dofile)
public static void lua_getglobal (LuaCore.lua_State luaState, string name) return LuaCore.lua_pcall (luaState, 0, -1, 0);
{ }
lua_pushstring (luaState, name);
LuaCore.lua_gettable (luaState, (int)LuaIndexes.Globals); // steffenj: END Lua 5.1.1 API change (lua_dofile now in LuaLib as luaL_dofile)
} public static void lua_getglobal (LuaCore.lua_State luaState, string name)
{
public static void lua_setglobal (LuaCore.lua_State luaState, string name) lua_pushstring (luaState, name);
{ LuaCore.lua_gettable (luaState, (int)LuaIndexes.Globals);
lua_pushstring (luaState, name); }
lua_insert (luaState, -2);
lua_settable (luaState, (int)LuaIndexes.Globals); public static void lua_setglobal (LuaCore.lua_State luaState, string name)
} {
lua_pushstring (luaState, name);
public static void lua_settop (LuaCore.lua_State luaState, int newTop) lua_insert (luaState, -2);
{ lua_settable (luaState, (int)LuaIndexes.Globals);
LuaCore.lua_settop (luaState, newTop); }
}
public static void lua_settop (LuaCore.lua_State luaState, int newTop)
public static void lua_pop (LuaCore.lua_State luaState, int amount) {
{ LuaCore.lua_settop (luaState, newTop);
lua_settop (luaState, -(amount) - 1); }
}
public static void lua_pop (LuaCore.lua_State luaState, int amount)
public static void lua_insert (LuaCore.lua_State luaState, int newTop) {
{ lua_settop (luaState, -(amount) - 1);
LuaCore.lua_insert (luaState, newTop); }
}
public static void lua_insert (LuaCore.lua_State luaState, int newTop)
public static void lua_remove (LuaCore.lua_State luaState, int index) {
{ LuaCore.lua_insert (luaState, newTop);
LuaCore.lua_remove (luaState, index); }
}
public static void lua_remove (LuaCore.lua_State luaState, int index)
public static void lua_gettable (LuaCore.lua_State luaState, int index) {
{ LuaCore.lua_remove (luaState, index);
LuaCore.lua_gettable (luaState, index); }
}
public static void lua_gettable (LuaCore.lua_State luaState, int index)
public static void lua_rawget (LuaCore.lua_State luaState, int index) {
{ LuaCore.lua_gettable (luaState, index);
LuaCore.lua_rawget (luaState, index); }
}
public static void lua_rawget (LuaCore.lua_State luaState, int index)
public static void lua_settable (LuaCore.lua_State luaState, int index) {
{ LuaCore.lua_rawget (luaState, index);
LuaCore.lua_settable (luaState, index); }
}
public static void lua_settable (LuaCore.lua_State luaState, int index)
public static void lua_rawset (LuaCore.lua_State luaState, int index) {
{ LuaCore.lua_settable (luaState, index);
LuaCore.lua_rawset (luaState, index); }
}
public static void lua_rawset (LuaCore.lua_State luaState, int index)
public static void lua_setmetatable (LuaCore.lua_State luaState, int objIndex) {
{ LuaCore.lua_rawset (luaState, index);
LuaCore.lua_setmetatable (luaState, objIndex); }
}
public static void lua_setmetatable (LuaCore.lua_State luaState, int objIndex)
public static int lua_getmetatable (LuaCore.lua_State luaState, int objIndex) {
{ LuaCore.lua_setmetatable (luaState, objIndex);
return LuaCore.lua_getmetatable (luaState, objIndex); }
}
public static int lua_getmetatable (LuaCore.lua_State luaState, int objIndex)
public static int lua_equal (LuaCore.lua_State luaState, int index1, int index2) {
{ return LuaCore.lua_getmetatable (luaState, objIndex);
return LuaCore.lua_equal (luaState, index1, index2); }
}
public static int lua_equal (LuaCore.lua_State luaState, int index1, int index2)
public static void lua_pushvalue (LuaCore.lua_State luaState, int index) {
{ return LuaCore.lua_equal (luaState, index1, index2);
LuaCore.lua_pushvalue (luaState, index); }
}
public static void lua_pushvalue (LuaCore.lua_State luaState, int index)
public static void lua_replace (LuaCore.lua_State luaState, int index) {
{ LuaCore.lua_pushvalue (luaState, index);
LuaCore.lua_replace (luaState, index); }
}
public static void lua_replace (LuaCore.lua_State luaState, int index)
public static int lua_gettop (LuaCore.lua_State luaState) {
{ LuaCore.lua_replace (luaState, index);
return LuaCore.lua_gettop (luaState); }
}
public static int lua_gettop (LuaCore.lua_State luaState)
public static LuaTypes lua_type (LuaCore.lua_State luaState, int index) {
{ return LuaCore.lua_gettop (luaState);
return (LuaTypes)LuaCore.lua_type (luaState, index); }
}
public static LuaTypes lua_type (LuaCore.lua_State luaState, int index)
public static bool lua_isnil (LuaCore.lua_State luaState, int index) {
{ return (LuaTypes)LuaCore.lua_type (luaState, index);
return lua_type (luaState, index) == LuaTypes.Nil; }
}
public static bool lua_isnil (LuaCore.lua_State luaState, int index)
public static bool lua_isnumber (LuaCore.lua_State luaState, int index) {
{ return lua_type (luaState, index) == LuaTypes.Nil;
return lua_type (luaState, index) == LuaTypes.Number; }
}
public static bool lua_isnumber (LuaCore.lua_State luaState, int index)
public static bool lua_isboolean (LuaCore.lua_State luaState, int index) {
{ return lua_type (luaState, index) == LuaTypes.Number;
return lua_type (luaState, index) == LuaTypes.Boolean; }
}
public static bool lua_isboolean (LuaCore.lua_State luaState, int index)
public static int luaL_ref (LuaCore.lua_State luaState, int registryIndex) {
{ return lua_type (luaState, index) == LuaTypes.Boolean;
return LuaCore.luaL_ref (luaState, registryIndex); }
}
public static int luaL_ref (LuaCore.lua_State luaState, int registryIndex)
public static int lua_ref (LuaCore.lua_State luaState, int lockRef) {
{ return LuaCore.luaL_ref (luaState, registryIndex);
return lockRef != 0 ? luaL_ref (luaState, (int)LuaIndexes.Registry) : 0; }
}
public static int lua_ref (LuaCore.lua_State luaState, int lockRef)
public static void lua_rawgeti (LuaCore.lua_State luaState, int tableIndex, int index) {
{ return lockRef != 0 ? luaL_ref (luaState, (int)LuaIndexes.Registry) : 0;
LuaCore.lua_rawgeti (luaState, tableIndex, index); }
}
public static void lua_rawgeti (LuaCore.lua_State luaState, int tableIndex, int index)
public static void lua_rawseti (LuaCore.lua_State luaState, int tableIndex, int index) {
{ LuaCore.lua_rawgeti (luaState, tableIndex, index);
LuaCore.lua_rawseti (luaState, tableIndex, index); }
}
public static void lua_rawseti (LuaCore.lua_State luaState, int tableIndex, int index)
public static object lua_newuserdata (LuaCore.lua_State luaState, int size) {
{ LuaCore.lua_rawseti (luaState, tableIndex, index);
return LuaCore.lua_newuserdata (luaState, (uint)size); }
}
public static object lua_newuserdata (LuaCore.lua_State luaState, int size)
public static object lua_touserdata (LuaCore.lua_State luaState, int index) {
{ return LuaCore.lua_newuserdata (luaState, (uint)size);
return LuaCore.lua_touserdata (luaState, index); }
}
public static object lua_touserdata (LuaCore.lua_State luaState, int index)
public static void lua_getref (LuaCore.lua_State luaState, int reference) {
{ return LuaCore.lua_touserdata (luaState, index);
lua_rawgeti (luaState, (int)LuaIndexes.Registry, reference); }
}
public static void lua_getref (LuaCore.lua_State luaState, int reference)
public static void lua_unref (LuaCore.lua_State luaState, int reference) {
{ lua_rawgeti (luaState, (int)LuaIndexes.Registry, reference);
LuaCore.luaL_unref (luaState, (int)LuaIndexes.Registry, reference); }
}
public static void lua_unref (LuaCore.lua_State luaState, int reference)
public static bool lua_isstring (LuaCore.lua_State luaState, int index) {
{ LuaCore.luaL_unref (luaState, (int)LuaIndexes.Registry, reference);
return LuaCore.lua_isstring (luaState, index) != 0; }
}
public static bool lua_isstring (LuaCore.lua_State luaState, int index)
public static bool lua_iscfunction (LuaCore.lua_State luaState, int index) {
{ return LuaCore.lua_isstring (luaState, index) != 0;
return LuaCore.lua_iscfunction (luaState, index); }
}
public static bool lua_iscfunction (LuaCore.lua_State luaState, int index)
public static void lua_pushnil (LuaCore.lua_State luaState) {
{ return LuaCore.lua_iscfunction (luaState, index);
LuaCore.lua_pushnil (luaState); }
}
public static void lua_pushnil (LuaCore.lua_State luaState)
public static void lua_call (LuaCore.lua_State luaState, int nArgs, int nResults) {
{ LuaCore.lua_pushnil (luaState);
LuaCore.lua_call (luaState, nArgs, nResults); }
}
public static void lua_call (LuaCore.lua_State luaState, int nArgs, int nResults)
public static void lua_pushstdcallcfunction (LuaCore.lua_State luaState, LuaCore.lua_CFunction function) {
{ LuaCore.lua_call (luaState, nArgs, nResults);
LuaCore.lua_pushcfunction (luaState, function); }
}
public static void lua_pushstdcallcfunction (LuaCore.lua_State luaState, LuaCore.lua_CFunction function)
public static int lua_pcall (LuaCore.lua_State luaState, int nArgs, int nResults, int errfunc) {
{ LuaCore.lua_pushcfunction (luaState, function);
return LuaCore.lua_pcall (luaState, nArgs, nResults, errfunc); }
}
public static int lua_pcall (LuaCore.lua_State luaState, int nArgs, int nResults, int errfunc)
public static LuaCore.lua_CFunction lua_tocfunction (LuaCore.lua_State luaState, int index) {
{ return LuaCore.lua_pcall (luaState, nArgs, nResults, errfunc);
return LuaCore.lua_tocfunction (luaState, index); }
}
public static LuaCore.lua_CFunction lua_tocfunction (LuaCore.lua_State luaState, int index)
public static double lua_tonumber (LuaCore.lua_State luaState, int index) {
{ return LuaCore.lua_tocfunction (luaState, index);
return LuaCore.lua_tonumber (luaState, index); }
}
public static double lua_tonumber (LuaCore.lua_State luaState, int index)
public static bool lua_toboolean (LuaCore.lua_State luaState, int index) {
{ return LuaCore.lua_tonumber (luaState, index);
return LuaCore.lua_toboolean (luaState, index) != 0; }
}
public static bool lua_toboolean (LuaCore.lua_State luaState, int index)
public static string lua_tostring (LuaCore.lua_State luaState, int index) {
{ return LuaCore.lua_toboolean (luaState, index) != 0;
#if true }
// FIXME use the same format string as lua i.e. LUA_NUMBER_FMT
var t = lua_type (luaState, index); public static string lua_tostring (LuaCore.lua_State luaState, int index)
{
if (t == LuaTypes.Number) #if true
return string.Format ("{0}", lua_tonumber (luaState, index)); // FIXME use the same format string as lua i.e. LUA_NUMBER_FMT
else if (t == LuaTypes.String) { var t = lua_type (luaState, index);
uint strlen;
return LuaCore.lua_tolstring (luaState, index, out strlen).ToString (); if (t == LuaTypes.Number)
} else if (t == LuaTypes.Nil) return string.Format ("{0}", lua_tonumber (luaState, index));
return null; // treat lua nulls to as C# nulls else if (t == LuaTypes.String) {
else uint strlen;
return "0"; // Because luaV_tostring does this return LuaCore.lua_tolstring (luaState, index, out strlen).ToString ();
#else } else if (t == LuaTypes.Nil)
size_t strlen; return null; // treat lua nulls to as C# nulls
else
// Note! This method will _change_ the representation of the object on the stack to a string. return "0"; // Because luaV_tostring does this
// We do not want this behavior so we do the conversion ourselves #else
const char *str = LuaCore.lua_tolstring(luaState, index, &strlen); size_t strlen;
if (str)
return Marshal::PtrToStringAnsi(IntPtr((char *) str), strlen); // Note! This method will _change_ the representation of the object on the stack to a string.
else // We do not want this behavior so we do the conversion ourselves
return nullptr; // treat lua nulls to as C# nulls const char *str = LuaCore.lua_tolstring(luaState, index, &strlen);
#endif if (str)
} return Marshal::PtrToStringAnsi(IntPtr((char *) str), strlen);
else
public static void lua_atpanic (LuaCore.lua_State luaState, LuaCore.lua_CFunction panicf) return nullptr; // treat lua nulls to as C# nulls
{ #endif
LuaCore.lua_atpanic (luaState, (LuaCore.lua_CFunction)panicf); }
}
public static void lua_atpanic (LuaCore.lua_State luaState, LuaCore.lua_CFunction panicf)
{
public static void lua_pushnumber (LuaCore.lua_State luaState, double number) LuaCore.lua_atpanic (luaState, (LuaCore.lua_CFunction)panicf);
{ }
LuaCore.lua_pushnumber (luaState, number);
}
public static void lua_pushnumber (LuaCore.lua_State luaState, double number)
public static void lua_pushboolean (LuaCore.lua_State luaState, bool value) {
{ LuaCore.lua_pushnumber (luaState, number);
LuaCore.lua_pushboolean (luaState, value ? 1 : 0); }
}
public static void lua_pushboolean (LuaCore.lua_State luaState, bool value)
public static void lua_pushstring (LuaCore.lua_State luaState, string str) {
{ LuaCore.lua_pushboolean (luaState, value ? 1 : 0);
LuaCore.lua_pushstring (luaState, str); }
}
public static void lua_pushstring (LuaCore.lua_State luaState, string str)
public static int luaL_newmetatable (LuaCore.lua_State luaState, string meta) {
{ LuaCore.lua_pushstring (luaState, str);
return LuaCore.luaL_newmetatable (luaState, meta); }
}
public static int luaL_newmetatable (LuaCore.lua_State luaState, string meta)
// steffenj: BEGIN Lua 5.1.1 API change (luaL_getmetatable is now a macro using lua_getfield) {
public static void lua_getfield (LuaCore.lua_State luaState, int stackPos, string meta) return LuaCore.luaL_newmetatable (luaState, meta);
{ }
LuaCore.lua_getfield (luaState, stackPos, meta);
} // steffenj: BEGIN Lua 5.1.1 API change (luaL_getmetatable is now a macro using lua_getfield)
public static void lua_getfield (LuaCore.lua_State luaState, int stackPos, string meta)
public static void luaL_getmetatable (LuaCore.lua_State luaState, string meta) {
{ LuaCore.lua_getfield (luaState, stackPos, meta);
lua_getfield (luaState, (int)LuaIndexes.Registry, meta); }
}
public static void luaL_getmetatable (LuaCore.lua_State luaState, string meta)
public static object luaL_checkudata (LuaCore.lua_State luaState, int stackPos, string meta) {
{ lua_getfield (luaState, (int)LuaIndexes.Registry, meta);
return LuaCore.luaL_checkudata (luaState, stackPos, meta); }
}
public static object luaL_checkudata (LuaCore.lua_State luaState, int stackPos, string meta)
public static bool luaL_getmetafield (LuaCore.lua_State luaState, int stackPos, string field) {
{ return LuaCore.luaL_checkudata (luaState, stackPos, meta);
return LuaCore.luaL_getmetafield (luaState, stackPos, field) != 0; }
}
public static bool luaL_getmetafield (LuaCore.lua_State luaState, int stackPos, string field)
public static int luaL_loadbuffer (LuaCore.lua_State luaState, string buff, string name) {
{ return LuaCore.luaL_getmetafield (luaState, stackPos, field) != 0;
return LuaCore.luaL_loadbuffer (luaState, buff, (uint)buff.Length, name); }
}
public static int luaL_loadbuffer (LuaCore.lua_State luaState, string buff, string name)
public static int luaL_loadfile (LuaCore.lua_State luaState, string filename) {
{ return LuaCore.luaL_loadbuffer (luaState, buff, (uint)buff.Length, name);
return LuaCore.luaL_loadfile (luaState, filename); }
}
public static int luaL_loadfile (LuaCore.lua_State luaState, string filename)
public static bool luaL_checkmetatable (LuaCore.lua_State luaState, int index) {
{ return LuaCore.luaL_loadfile (luaState, filename);
return LuaCore.luaL_checkmetatable (luaState, index); }
}
public static bool luaL_checkmetatable (LuaCore.lua_State luaState, int index)
public static int luanet_tonetobject (LuaCore.lua_State luaState, int index) {
{ return LuaCore.luaL_checkmetatable (luaState, index);
return LuaCore.luanet_tonetobject (luaState, index); }
}
public static int luanet_tonetobject (LuaCore.lua_State luaState, int index)
public static void luanet_newudata (LuaCore.lua_State luaState, int val) {
{ return LuaCore.luanet_tonetobject (luaState, index);
LuaCore.luanet_newudata (luaState, val); }
}
public static void luanet_newudata (LuaCore.lua_State luaState, int val)
public static int luanet_rawnetobj (LuaCore.lua_State luaState, int obj) {
{ LuaCore.luanet_newudata (luaState, val);
return LuaCore.luanet_rawnetobj (luaState, obj); }
}
public static int luanet_rawnetobj (LuaCore.lua_State luaState, int obj)
public static int luanet_checkudata (LuaCore.lua_State luaState, int ud, string tname) {
{ return LuaCore.luanet_rawnetobj (luaState, obj);
return LuaCore.luanet_checkudata (luaState, ud, tname); }
}
public static int luanet_checkudata (LuaCore.lua_State luaState, int ud, string tname)
public static void lua_error (LuaCore.lua_State luaState) {
{ return LuaCore.luanet_checkudata (luaState, ud, tname);
LuaCore.lua_error (luaState); }
}
public static void lua_error (LuaCore.lua_State luaState)
public static bool lua_checkstack (LuaCore.lua_State luaState, int extra) {
{ LuaCore.lua_error (luaState);
return LuaCore.lua_checkstack (luaState, extra) != 0; }
}
public static bool lua_checkstack (LuaCore.lua_State luaState, int extra)
public static int lua_next (LuaCore.lua_State luaState, int index) {
{ return LuaCore.lua_checkstack (luaState, extra) != 0;
return LuaCore.lua_next (luaState, index); }
}
public static int lua_next (LuaCore.lua_State luaState, int index)
public static void lua_pushlightuserdata (LuaCore.lua_State luaState, LuaCore.LuaTag udata) {
{ return LuaCore.lua_next (luaState, index);
LuaCore.lua_pushlightuserdata (luaState, udata.Tag); }
}
public static void lua_pushlightuserdata (LuaCore.lua_State luaState, LuaCore.LuaTag udata)
public static LuaCore.LuaTag luanet_gettag () {
{ LuaCore.lua_pushlightuserdata (luaState, udata.Tag);
return LuaCore.luanet_gettag (); }
}
public static LuaCore.LuaTag luanet_gettag ()
} {
return LuaCore.luanet_gettag ();
}
}
} }
\ No newline at end of file
/* /*
* This file is part of LuaInterface. * This file is part of LuaInterface.
* *
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz. * Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/> * Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*/ */
using System; using System;
using System.Text; using System.Text;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
namespace LuaInterface namespace LuaInterface
{ {
using LuaCore = KeraLua.Lua; #if USE_KOPILUA
using LuaCore = KopiLua.Lua;
/* #else
* Wrapper class for Lua tables using LuaCore = KeraLua.Lua;
* #endif
* Author: Fabio Mascarenhas
* Version: 1.0 /*
*/ * Wrapper class for Lua tables
public class LuaTable : LuaBase *
{ * Author: Fabio Mascarenhas
public LuaTable (int reference, Lua interpreter) * Version: 1.0
{ */
_Reference = reference; public class LuaTable : LuaBase
_Interpreter = interpreter; {
} public LuaTable (int reference, Lua interpreter)
{
/* _Reference = reference;
* Indexer for string fields of the table _Interpreter = interpreter;
*/ }
public object this [string field] {
get { /*
return _Interpreter.getObject (_Reference, field); * Indexer for string fields of the table
} */
set { public object this [string field] {
_Interpreter.setObject (_Reference, field, value); get {
} return _Interpreter.getObject (_Reference, field);
} }
set {
/* _Interpreter.setObject (_Reference, field, value);
* Indexer for numeric fields of the table }
*/ }
public object this [object field] {
get { /*
return _Interpreter.getObject (_Reference, field); * Indexer for numeric fields of the table
} */
set { public object this [object field] {
_Interpreter.setObject (_Reference, field, value); get {
} return _Interpreter.getObject (_Reference, field);
} }
set {
public System.Collections.IDictionaryEnumerator GetEnumerator () _Interpreter.setObject (_Reference, field, value);
{ }
return _Interpreter.GetTableDict (this).GetEnumerator (); }
}
public System.Collections.IDictionaryEnumerator GetEnumerator ()
public ICollection Keys { {
get { return _Interpreter.GetTableDict (this).Keys; } return _Interpreter.GetTableDict (this).GetEnumerator ();
} }
public ICollection Values { public ICollection Keys {
get { return _Interpreter.GetTableDict (this).Values; } get { return _Interpreter.GetTableDict (this).Keys; }
} }
/* public ICollection Values {
* Gets an string fields of a table ignoring its metatable, get { return _Interpreter.GetTableDict (this).Values; }
* if it exists }
*/
internal object rawget (string field) /*
{ * Gets an string fields of a table ignoring its metatable,
return _Interpreter.rawGetObject (_Reference, field); * if it exists
} */
internal object rawget (string field)
internal object rawgetFunction (string field) {
{ return _Interpreter.rawGetObject (_Reference, field);
object obj = _Interpreter.rawGetObject (_Reference, field); }
if (obj is LuaCore.lua_CFunction) internal object rawgetFunction (string field)
return new LuaFunction ((LuaCore.lua_CFunction)obj, _Interpreter); {
else object obj = _Interpreter.rawGetObject (_Reference, field);
return obj;
} if (obj is LuaCore.lua_CFunction)
return new LuaFunction ((LuaCore.lua_CFunction)obj, _Interpreter);
/* else
* Pushes this table into the Lua stack return obj;
*/ }
internal void push (LuaCore.lua_State luaState)
{ /*
LuaLib.lua_getref (luaState, _Reference); * Pushes this table into the Lua stack
} */
internal void push (LuaCore.lua_State luaState)
public override string ToString () {
{ LuaLib.lua_getref (luaState, _Reference);
return "table"; }
}
} public override string ToString ()
{
return "table";
}
}
} }
\ No newline at end of file
/* /*
* This file is part of LuaInterface. * This file is part of LuaInterface.
* *
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz. * Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/> * Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*/ */
using System; using System;
using System.Text; using System.Text;
using System.Collections.Generic; using System.Collections.Generic;
namespace LuaInterface namespace LuaInterface
{ {
using LuaCore = KeraLua.Lua; #if USE_KOPILUA
using LuaCore = KopiLua.Lua;
public class LuaUserData : LuaBase #else
{ using LuaCore = KeraLua.Lua;
public LuaUserData (int reference, Lua interpreter) #endif
{
_Reference = reference; public class LuaUserData : LuaBase
_Interpreter = interpreter; {
} public LuaUserData (int reference, Lua interpreter)
{
/* _Reference = reference;
* Indexer for string fields of the userdata _Interpreter = interpreter;
*/ }
public object this [string field] {
get { /*
return _Interpreter.getObject (_Reference, field); * Indexer for string fields of the userdata
} */
set { public object this [string field] {
_Interpreter.setObject (_Reference, field, value); get {
} return _Interpreter.getObject (_Reference, field);
} }
set {
/* _Interpreter.setObject (_Reference, field, value);
* Indexer for numeric fields of the userdata }
*/ }
public object this [object field] {
get { /*
return _Interpreter.getObject (_Reference, field); * Indexer for numeric fields of the userdata
} */
set { public object this [object field] {
_Interpreter.setObject (_Reference, field, value); get {
} return _Interpreter.getObject (_Reference, field);
} }
set {
/* _Interpreter.setObject (_Reference, field, value);
* Calls the userdata and returns its return values inside }
* an array }
*/
public object[] Call (params object[] args) /*
{ * Calls the userdata and returns its return values inside
return _Interpreter.callFunction (this, args); * an array
} */
public object[] Call (params object[] args)
/* {
* Pushes the userdata into the Lua stack return _Interpreter.callFunction (this, args);
*/ }
internal void push (LuaCore.lua_State luaState)
{ /*
LuaLib.lua_getref (luaState, _Reference); * Pushes the userdata into the Lua stack
} */
internal void push (LuaCore.lua_State luaState)
public override string ToString () {
{ LuaLib.lua_getref (luaState, _Reference);
return "userdata"; }
}
} public override string ToString ()
{
return "userdata";
}
}
} }
\ No newline at end of file
/* /*
* This file is part of LuaInterface. * This file is part of LuaInterface.
* *
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz. * Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/> * Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*/ */
using System; using System;
using System.IO; using System.IO;
using System.Collections; using System.Collections;
using System.Reflection; using System.Reflection;
using System.Diagnostics; using System.Diagnostics;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using LuaInterface.Method; using LuaInterface.Method;
using LuaInterface.Extensions; using LuaInterface.Extensions;
namespace LuaInterface namespace LuaInterface
{ {
using LuaCore = KeraLua.Lua; #if USE_KOPILUA
using LuaCore = KopiLua.Lua;
/* #else
* Functions used in the metatables of userdata representing using LuaCore = KeraLua.Lua;
* CLR objects #endif
*
* Author: Fabio Mascarenhas /*
* Version: 1.0 * Functions used in the metatables of userdata representing
*/ * CLR objects
class MetaFunctions *
{ * Author: Fabio Mascarenhas
internal LuaCore.lua_CFunction gcFunction, indexFunction, newindexFunction, baseIndexFunction, * Version: 1.0
classIndexFunction, classNewindexFunction, execDelegateFunction, callConstructorFunction, toStringFunction; */
private Hashtable memberCache = new Hashtable (); public class MetaFunctions
private ObjectTranslator translator; {
internal LuaCore.lua_CFunction gcFunction, indexFunction, newindexFunction, baseIndexFunction,
/* classIndexFunction, classNewindexFunction, execDelegateFunction, callConstructorFunction, toStringFunction;
* __index metafunction for CLR objects. Implemented in Lua. private Hashtable memberCache = new Hashtable ();
*/ private ObjectTranslator translator;
internal static string luaIndexFunction =
"local function index(obj,name) \n" + /*
" local meta=getmetatable(obj) \n" + * __index metafunction for CLR objects. Implemented in Lua.
" local cached=meta.cache[name] \n" + */
" if cached~=nil then \n" + internal static string luaIndexFunction =
" return cached \n" + "local function index(obj,name) \n" +
" else \n" + " local meta=getmetatable(obj) \n" +
" local value,isFunc=get_object_member(obj,name) \n" + " local cached=meta.cache[name] \n" +
" if isFunc then \n" + " if cached~=nil then \n" +
" meta.cache[name]=value \n" + " return cached \n" +
" end \n" + " else \n" +
" return value \n" + " local value,isFunc=get_object_member(obj,name) \n" +
" end \n" + " if isFunc then \n" +
"end \n" + " meta.cache[name]=value \n" +
"return index "; " end \n" +
" return value \n" +
public MetaFunctions (ObjectTranslator translator) " end \n" +
{ "end \n" +
this.translator = translator; "return index ";
gcFunction = new LuaCore.lua_CFunction (this.collectObject);
toStringFunction = new LuaCore.lua_CFunction (this.toString); public MetaFunctions (ObjectTranslator translator)
indexFunction = new LuaCore.lua_CFunction (this.getMethod); {
newindexFunction = new LuaCore.lua_CFunction (this.setFieldOrProperty); this.translator = translator;
baseIndexFunction = new LuaCore.lua_CFunction (this.getBaseMethod); gcFunction = new LuaCore.lua_CFunction (MetaFunctions.collectObject);
callConstructorFunction = new LuaCore.lua_CFunction (this.callConstructor); toStringFunction = new LuaCore.lua_CFunction (MetaFunctions.toString);
classIndexFunction = new LuaCore.lua_CFunction (this.getClassMethod); indexFunction = new LuaCore.lua_CFunction (MetaFunctions.getMethod);
classNewindexFunction = new LuaCore.lua_CFunction (this.setClassFieldOrProperty); newindexFunction = new LuaCore.lua_CFunction (MetaFunctions.setFieldOrProperty);
execDelegateFunction = new LuaCore.lua_CFunction (this.runFunctionDelegate); baseIndexFunction = new LuaCore.lua_CFunction (MetaFunctions.getBaseMethod);
} callConstructorFunction = new LuaCore.lua_CFunction (MetaFunctions.callConstructor);
classIndexFunction = new LuaCore.lua_CFunction (MetaFunctions.getClassMethod);
/* classNewindexFunction = new LuaCore.lua_CFunction (MetaFunctions.setClassFieldOrProperty);
* __call metafunction of CLR delegates, retrieves and calls the delegate. execDelegateFunction = new LuaCore.lua_CFunction (MetaFunctions.runFunctionDelegate);
*/ }
/*
* __call metafunction of CLR delegates, retrieves and calls the delegate.
*/
#if MONOTOUCH #if MONOTOUCH
[MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_CFunction))] [MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_CFunction))]
#endif #endif
[System.Runtime.InteropServices.AllowReversePInvokeCalls] [System.Runtime.InteropServices.AllowReversePInvokeCalls]
private int runFunctionDelegate (LuaCore.lua_State luaState) private static int runFunctionDelegate (LuaCore.lua_State luaState)
{ {
LuaCore.lua_CFunction func = (LuaCore.lua_CFunction)translator.getRawNetObject (luaState, 1); var translator = ObjectTranslatorPool.Instance.Find (luaState);
LuaLib.lua_remove (luaState, 1); return runFunctionDelegate (luaState, translator);
return func (luaState); }
}
private static int runFunctionDelegate (LuaCore.lua_State luaState, ObjectTranslator translator)
/* {
* __gc metafunction of CLR objects. LuaCore.lua_CFunction func = (LuaCore.lua_CFunction)translator.getRawNetObject (luaState, 1);
*/ LuaLib.lua_remove (luaState, 1);
return func (luaState);
}
/*
* __gc metafunction of CLR objects.
*/
#if MONOTOUCH #if MONOTOUCH
[MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_CFunction))] [MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_CFunction))]
#endif #endif
[System.Runtime.InteropServices.AllowReversePInvokeCalls] [System.Runtime.InteropServices.AllowReversePInvokeCalls]
private int collectObject (LuaCore.lua_State luaState) private static int collectObject (LuaCore.lua_State luaState)
{ {
int udata = LuaLib.luanet_rawnetobj (luaState, 1); var translator = ObjectTranslatorPool.Instance.Find (luaState);
return collectObject (luaState, translator);
if (udata != -1) }
translator.collectObject (udata);
else { private static int collectObject (LuaCore.lua_State luaState, ObjectTranslator translator)
// Debug.WriteLine("not found: " + udata); {
} int udata = LuaLib.luanet_rawnetobj (luaState, 1);
return 0; if (udata != -1)
} translator.collectObject (udata);
/* return 0;
* __tostring metafunction of CLR objects. }
*/
/*
* __tostring metafunction of CLR objects.
*/
#if MONOTOUCH #if MONOTOUCH
[MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_CFunction))] [MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_CFunction))]
#endif #endif
[System.Runtime.InteropServices.AllowReversePInvokeCalls] [System.Runtime.InteropServices.AllowReversePInvokeCalls]
private int toString (LuaCore.lua_State luaState) private static int toString (LuaCore.lua_State luaState)
{ {
object obj = translator.getRawNetObject (luaState, 1); var translator = ObjectTranslatorPool.Instance.Find (luaState);
return toString (luaState, translator);
if (!obj.IsNull ()) }
translator.push (luaState, obj.ToString () + ": " + obj.GetHashCode ());
else private static int toString (LuaCore.lua_State luaState, ObjectTranslator translator)
LuaLib.lua_pushnil (luaState); {
object obj = translator.getRawNetObject (luaState, 1);
return 1;
} if (!obj.IsNull ())
translator.push (luaState, obj.ToString () + ": " + obj.GetHashCode ());
else
/// <summary> LuaLib.lua_pushnil (luaState);
/// Debug tool to dump the lua stack
/// </summary> return 1;
/// FIXME, move somewhere else }
public static void dumpStack (ObjectTranslator translator, LuaCore.lua_State luaState)
{
int depth = LuaLib.lua_gettop (luaState); /// <summary>
Debug.WriteLine ("lua stack depth: " + depth); /// Debug tool to dump the lua stack
/// </summary>
for (int i = 1; i <= depth; i++) { /// FIXME, move somewhere else
var type = LuaLib.lua_type (luaState, i); public static void dumpStack (ObjectTranslator translator, LuaCore.lua_State luaState)
// we dump stacks when deep in calls, calling typename while the stack is in flux can fail sometimes, so manually check for key types {
string typestr = (type == LuaTypes.Table) ? "table" : LuaLib.lua_typename (luaState, type); int depth = LuaLib.lua_gettop (luaState);
string strrep = LuaLib.lua_tostring (luaState, i).ToString (); Debug.WriteLine ("lua stack depth: " + depth);
if (type == LuaTypes.UserData) { for (int i = 1; i <= depth; i++) {
object obj = translator.getRawNetObject (luaState, i); var type = LuaLib.lua_type (luaState, i);
strrep = obj.ToString (); // we dump stacks when deep in calls, calling typename while the stack is in flux can fail sometimes, so manually check for key types
} string typestr = (type == LuaTypes.Table) ? "table" : LuaLib.lua_typename (luaState, type);
string strrep = LuaLib.lua_tostring (luaState, i).ToString ();
Debug.Print ("{0}: ({1}) {2}", i, typestr, strrep);
} if (type == LuaTypes.UserData) {
} object obj = translator.getRawNetObject (luaState, i);
strrep = obj.ToString ();
/* }
* Called by the __index metafunction of CLR objects in case the
* method is not cached or it is a field/property/event. Debug.Print ("{0}: ({1}) {2}", i, typestr, strrep);
* Receives the object and the member name as arguments and returns }
* either the value of the member or a delegate to call it. }
* If the member does not exist returns nil.
*/ /*
* Called by the __index metafunction of CLR objects in case the
* method is not cached or it is a field/property/event.
* Receives the object and the member name as arguments and returns
* either the value of the member or a delegate to call it.
* If the member does not exist returns nil.
*/
#if MONOTOUCH #if MONOTOUCH
[MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_CFunction))] [MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_CFunction))]
#endif #endif
[System.Runtime.InteropServices.AllowReversePInvokeCalls] [System.Runtime.InteropServices.AllowReversePInvokeCalls]
private int getMethod (LuaCore.lua_State luaState) private static int getMethod (LuaCore.lua_State luaState)
{ {
object obj = translator.getRawNetObject (luaState, 1); var translator = ObjectTranslatorPool.Instance.Find (luaState);
var instance = translator.MetaFunctionsInstance;
if (obj.IsNull ()) { return instance.getMethodInternal (luaState);
translator.throwError (luaState, "trying to index an invalid object reference"); }
LuaLib.lua_pushnil (luaState);
return 1; private int getMethodInternal (LuaCore.lua_State luaState)
} {
object obj = translator.getRawNetObject (luaState, 1);
object index = translator.getObject (luaState, 2);
//var indexType = index.GetType(); if (obj.IsNull ()) {
string methodName = index as string; // will be null if not a string arg translator.throwError (luaState, "trying to index an invalid object reference");
var objType = obj.GetType (); LuaLib.lua_pushnil (luaState);
return 1;
// Handle the most common case, looking up the method by name. }
// CP: This will fail when using indexers and attempting to get a value with the same name as a property of the object, object index = translator.getObject (luaState, 2);
// ie: xmlelement['item'] <- item is a property of xmlelement //var indexType = index.GetType();
try { string methodName = index as string; // will be null if not a string arg
if (!methodName.IsNull () && isMemberPresent (objType, methodName)) var objType = obj.GetType ();
return getMember (luaState, objType, obj, methodName, BindingFlags.Instance | BindingFlags.IgnoreCase);
} catch { // Handle the most common case, looking up the method by name.
}
// CP: This will fail when using indexers and attempting to get a value with the same name as a property of the object,
// Try to access by array if the type is right and index is an int (lua numbers always come across as double) // ie: xmlelement['item'] <- item is a property of xmlelement
if (objType.IsArray && index is double) { try {
int intIndex = (int)((double)index); if (!methodName.IsNull () && isMemberPresent (objType, methodName))
return getMember (luaState, objType, obj, methodName, BindingFlags.Instance | BindingFlags.IgnoreCase);
if (objType.UnderlyingSystemType == typeof(float[])) { } catch {
float[] arr = ((float[])obj); }
translator.push (luaState, arr [intIndex]);
} else if (objType.UnderlyingSystemType == typeof(double[])) { // Try to access by array if the type is right and index is an int (lua numbers always come across as double)
double[] arr = ((double[])obj); if (objType.IsArray && index is double) {
translator.push (luaState, arr [intIndex]); int intIndex = (int)((double)index);
} else if (objType.UnderlyingSystemType == typeof(int[])) {
int[] arr = ((int[])obj); if (objType.UnderlyingSystemType == typeof(float[])) {
translator.push (luaState, arr [intIndex]); float[] arr = ((float[])obj);
} else { translator.push (luaState, arr [intIndex]);
object[] arr = (object[])obj; } else if (objType.UnderlyingSystemType == typeof(double[])) {
translator.push (luaState, arr [intIndex]); double[] arr = ((double[])obj);
} translator.push (luaState, arr [intIndex]);
} else { } else if (objType.UnderlyingSystemType == typeof(int[])) {
// Try to use get_Item to index into this .net object int[] arr = ((int[])obj);
//MethodInfo getter = objType.GetMethod("get_Item"); translator.push (luaState, arr [intIndex]);
var methods = objType.GetMethods (); } else {
object[] arr = (object[])obj;
foreach (var mInfo in methods) { translator.push (luaState, arr [intIndex]);
if (mInfo.Name == "get_Item") { }
//check if the signature matches the input } else {
if (mInfo.GetParameters ().Length == 1) { // Try to use get_Item to index into this .net object
var getter = mInfo; //MethodInfo getter = objType.GetMethod("get_Item");
var actualParms = (!getter.IsNull ()) ? getter.GetParameters () : null; var methods = objType.GetMethods ();
if (actualParms.IsNull () || actualParms.Length != 1) { foreach (var mInfo in methods) {
translator.throwError (luaState, "method not found (or no indexer): " + index); if (mInfo.Name == "get_Item") {
LuaLib.lua_pushnil (luaState); //check if the signature matches the input
} else { if (mInfo.GetParameters ().Length == 1) {
// Get the index in a form acceptable to the getter var getter = mInfo;
index = translator.getAsType (luaState, 2, actualParms [0].ParameterType); var actualParms = (!getter.IsNull ()) ? getter.GetParameters () : null;
object[] args = new object[1];
if (actualParms.IsNull () || actualParms.Length != 1) {
// Just call the indexer - if out of bounds an exception will happen translator.throwError (luaState, "method not found (or no indexer): " + index);
args [0] = index; LuaLib.lua_pushnil (luaState);
} else {
try { // Get the index in a form acceptable to the getter
object result = getter.Invoke (obj, args); index = translator.getAsType (luaState, 2, actualParms [0].ParameterType);
translator.push (luaState, result); object[] args = new object[1];
} catch (TargetInvocationException e) {
// Provide a more readable description for the common case of key not found // Just call the indexer - if out of bounds an exception will happen
if (e.InnerException is KeyNotFoundException) args [0] = index;
translator.throwError (luaState, "key '" + index + "' not found ");
else try {
translator.throwError (luaState, "exception indexing '" + index + "' " + e.Message); object result = getter.Invoke (obj, args);
translator.push (luaState, result);
LuaLib.lua_pushnil (luaState); } catch (TargetInvocationException e) {
} // Provide a more readable description for the common case of key not found
} if (e.InnerException is KeyNotFoundException)
} translator.throwError (luaState, "key '" + index + "' not found ");
} else
} translator.throwError (luaState, "exception indexing '" + index + "' " + e.Message);
}
LuaLib.lua_pushnil (luaState);
LuaLib.lua_pushboolean (luaState, false); }
return 2; }
} }
}
/* }
* __index metafunction of base classes (the base field of Lua tables). }
* Adds a prefix to the method name to call the base version of the method.
*/ LuaLib.lua_pushboolean (luaState, false);
return 2;
}
/*
* __index metafunction of base classes (the base field of Lua tables).
* Adds a prefix to the method name to call the base version of the method.
*/
#if MONOTOUCH #if MONOTOUCH
[MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_CFunction))] [MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_CFunction))]
#endif #endif
[System.Runtime.InteropServices.AllowReversePInvokeCalls] [System.Runtime.InteropServices.AllowReversePInvokeCalls]
private int getBaseMethod (LuaCore.lua_State luaState) private static int getBaseMethod (LuaCore.lua_State luaState)
{ {
object obj = translator.getRawNetObject (luaState, 1); var translator = ObjectTranslatorPool.Instance.Find (luaState);
var instance = translator.MetaFunctionsInstance;
if (obj.IsNull ()) { return instance.getBaseMethodInternal (luaState);
translator.throwError (luaState, "trying to index an invalid object reference"); }
LuaLib.lua_pushnil (luaState);
LuaLib.lua_pushboolean (luaState, false); private int getBaseMethodInternal (LuaCore.lua_State luaState)
return 2; {
} object obj = translator.getRawNetObject (luaState, 1);
string methodName = LuaLib.lua_tostring (luaState, 2).ToString (); if (obj.IsNull ()) {
translator.throwError (luaState, "trying to index an invalid object reference");
if (methodName.IsNull ()) { LuaLib.lua_pushnil (luaState);
LuaLib.lua_pushnil (luaState); LuaLib.lua_pushboolean (luaState, false);
LuaLib.lua_pushboolean (luaState, false); return 2;
return 2; }
}
string methodName = LuaLib.lua_tostring (luaState, 2).ToString ();
getMember (luaState, obj.GetType (), obj, "__luaInterface_base_" + methodName, BindingFlags.Instance | BindingFlags.IgnoreCase);
LuaLib.lua_settop (luaState, -2); if (methodName.IsNull ()) {
LuaLib.lua_pushnil (luaState);
if (LuaLib.lua_type (luaState, -1) == LuaTypes.Nil) { LuaLib.lua_pushboolean (luaState, false);
LuaLib.lua_settop (luaState, -2); return 2;
return getMember (luaState, obj.GetType (), obj, methodName, BindingFlags.Instance | BindingFlags.IgnoreCase); }
}
getMember (luaState, obj.GetType (), obj, "__luaInterface_base_" + methodName, BindingFlags.Instance | BindingFlags.IgnoreCase);
LuaLib.lua_pushboolean (luaState, false); LuaLib.lua_settop (luaState, -2);
return 2;
} if (LuaLib.lua_type (luaState, -1) == LuaTypes.Nil) {
LuaLib.lua_settop (luaState, -2);
/// <summary> return getMember (luaState, obj.GetType (), obj, methodName, BindingFlags.Instance | BindingFlags.IgnoreCase);
/// Does this method exist as either an instance or static? }
/// </summary>
/// <param name="objType"></param> LuaLib.lua_pushboolean (luaState, false);
/// <param name="methodName"></param> return 2;
/// <returns></returns> }
bool isMemberPresent (IReflect objType, string methodName)
{ /// <summary>
object cachedMember = checkMemberCache (memberCache, objType, methodName); /// Does this method exist as either an instance or static?
/// </summary>
if (!cachedMember.IsNull ()) /// <param name="objType"></param>
return true; /// <param name="methodName"></param>
/// <returns></returns>
//CP: Removed NonPublic binding search bool isMemberPresent (IReflect objType, string methodName)
var members = objType.GetMember (methodName, BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase/* | BindingFlags.NonPublic*/); {
return (members.Length > 0); object cachedMember = checkMemberCache (memberCache, objType, methodName);
}
if (!cachedMember.IsNull ())
/* return true;
* Pushes the value of a member or a delegate to call it, depending on the type of
* the member. Works with static or instance members. //CP: Removed NonPublic binding search
* Uses reflection to find members, and stores the reflected MemberInfo object in var members = objType.GetMember (methodName, BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase/* | BindingFlags.NonPublic*/);
* a cache (indexed by the type of the object and the name of the member). return (members.Length > 0);
*/ }
private int getMember (LuaCore.lua_State luaState, IReflect objType, object obj, string methodName, BindingFlags bindingType)
{ /*
bool implicitStatic = false; * Pushes the value of a member or a delegate to call it, depending on the type of
MemberInfo member = null; * the member. Works with static or instance members.
object cachedMember = checkMemberCache (memberCache, objType, methodName); * Uses reflection to find members, and stores the reflected MemberInfo object in
//object cachedMember=null; * a cache (indexed by the type of the object and the name of the member).
*/
if (cachedMember is LuaCore.lua_CFunction) { private int getMember (LuaCore.lua_State luaState, IReflect objType, object obj, string methodName, BindingFlags bindingType)
translator.pushFunction (luaState, (LuaCore.lua_CFunction)cachedMember); {
translator.push (luaState, true); bool implicitStatic = false;
return 2; MemberInfo member = null;
} else if (!cachedMember.IsNull ()) object cachedMember = checkMemberCache (memberCache, objType, methodName);
member = (MemberInfo)cachedMember; //object cachedMember=null;
else {
//CP: Removed NonPublic binding search if (cachedMember is LuaCore.lua_CFunction) {
var members = objType.GetMember (methodName, bindingType | BindingFlags.Public | BindingFlags.IgnoreCase/*| BindingFlags.NonPublic*/); translator.pushFunction (luaState, (LuaCore.lua_CFunction)cachedMember);
translator.push (luaState, true);
if (members.Length > 0) return 2;
member = members [0]; } else if (!cachedMember.IsNull ())
else { member = (MemberInfo)cachedMember;
// If we can't find any suitable instance members, try to find them as statics - but we only want to allow implicit static else {
// lookups for fields/properties/events -kevinh //CP: Removed NonPublic binding search
//CP: Removed NonPublic binding search and made case insensitive var members = objType.GetMember (methodName, bindingType | BindingFlags.Public | BindingFlags.IgnoreCase/*| BindingFlags.NonPublic*/);
members = objType.GetMember (methodName, bindingType | BindingFlags.Static | BindingFlags.Public | BindingFlags.IgnoreCase/*| BindingFlags.NonPublic*/);
if (members.Length > 0)
if (members.Length > 0) { member = members [0];
member = members [0]; else {
implicitStatic = true; // If we can't find any suitable instance members, try to find them as statics - but we only want to allow implicit static
} // lookups for fields/properties/events -kevinh
} //CP: Removed NonPublic binding search and made case insensitive
} members = objType.GetMember (methodName, bindingType | BindingFlags.Static | BindingFlags.Public | BindingFlags.IgnoreCase/*| BindingFlags.NonPublic*/);
if (!member.IsNull ()) { if (members.Length > 0) {
if (member.MemberType == MemberTypes.Field) { member = members [0];
var field = (FieldInfo)member; implicitStatic = true;
}
if (cachedMember.IsNull ()) }
setMemberCache (memberCache, objType, methodName, member); }
try { if (!member.IsNull ()) {
translator.push (luaState, field.GetValue (obj)); if (member.MemberType == MemberTypes.Field) {
} catch { var field = (FieldInfo)member;
LuaLib.lua_pushnil (luaState);
} if (cachedMember.IsNull ())
} else if (member.MemberType == MemberTypes.Property) { setMemberCache (memberCache, objType, methodName, member);
var property = (PropertyInfo)member;
if (cachedMember.IsNull ()) try {
setMemberCache (memberCache, objType, methodName, member); translator.push (luaState, field.GetValue (obj));
} catch {
try { LuaLib.lua_pushnil (luaState);
object val = property.GetValue (obj, null); }
translator.push (luaState, val); } else if (member.MemberType == MemberTypes.Property) {
} catch (ArgumentException) { var property = (PropertyInfo)member;
// If we can't find the getter in our class, recurse up to the base class and see if (cachedMember.IsNull ())
// if they can help. setMemberCache (memberCache, objType, methodName, member);
if (objType is Type && !(((Type)objType) == typeof(object)))
return getMember (luaState, ((Type)objType).BaseType, obj, methodName, bindingType); try {
else object val = property.GetValue (obj, null);
LuaLib.lua_pushnil (luaState); translator.push (luaState, val);
} catch (TargetInvocationException e) { // Convert this exception into a Lua error } catch (ArgumentException) {
ThrowError (luaState, e); // If we can't find the getter in our class, recurse up to the base class and see
LuaLib.lua_pushnil (luaState); // if they can help.
} if (objType is Type && !(((Type)objType) == typeof(object)))
} else if (member.MemberType == MemberTypes.Event) { return getMember (luaState, ((Type)objType).BaseType, obj, methodName, bindingType);
var eventInfo = (EventInfo)member; else
if (cachedMember.IsNull ()) LuaLib.lua_pushnil (luaState);
setMemberCache (memberCache, objType, methodName, member); } catch (TargetInvocationException e) { // Convert this exception into a Lua error
ThrowError (luaState, e);
translator.push (luaState, new RegisterEventHandler (translator.pendingEvents, obj, eventInfo)); LuaLib.lua_pushnil (luaState);
} else if (!implicitStatic) { }
if (member.MemberType == MemberTypes.NestedType) { } else if (member.MemberType == MemberTypes.Event) {
// kevinh - added support for finding nested types var eventInfo = (EventInfo)member;
// cache us if (cachedMember.IsNull ())
if (cachedMember.IsNull ()) setMemberCache (memberCache, objType, methodName, member);
setMemberCache (memberCache, objType, methodName, member);
translator.push (luaState, new RegisterEventHandler (translator.pendingEvents, obj, eventInfo));
// Find the name of our class } else if (!implicitStatic) {
string name = member.Name; if (member.MemberType == MemberTypes.NestedType) {
var dectype = member.DeclaringType; // kevinh - added support for finding nested types
// cache us
// Build a new long name and try to find the type by name if (cachedMember.IsNull ())
string longname = dectype.FullName + "+" + name; setMemberCache (memberCache, objType, methodName, member);
var nestedType = translator.FindType (longname);
translator.pushType (luaState, nestedType); // Find the name of our class
} else { string name = member.Name;
// Member type must be 'method' var dectype = member.DeclaringType;
var wrapper = new LuaCore.lua_CFunction ((new LuaMethodWrapper (translator, objType, methodName, bindingType)).invokeFunction);
// Build a new long name and try to find the type by name
if (cachedMember.IsNull ()) string longname = dectype.FullName + "+" + name;
setMemberCache (memberCache, objType, methodName, wrapper); var nestedType = translator.FindType (longname);
translator.pushType (luaState, nestedType);
translator.pushFunction (luaState, wrapper); } else {
translator.push (luaState, true); // Member type must be 'method'
return 2; var wrapper = new LuaCore.lua_CFunction ((new LuaMethodWrapper (translator, objType, methodName, bindingType)).invokeFunction);
}
} else { if (cachedMember.IsNull ())
// If we reach this point we found a static method, but can't use it in this context because the user passed in an instance setMemberCache (memberCache, objType, methodName, wrapper);
translator.throwError (luaState, "can't pass instance to static method " + methodName);
LuaLib.lua_pushnil (luaState); translator.pushFunction (luaState, wrapper);
} translator.push (luaState, true);
} else { return 2;
// kevinh - we want to throw an exception because meerly returning 'nil' in this case }
// is not sufficient. valid data members may return nil and therefore there must be some } else {
// way to know the member just doesn't exist. // If we reach this point we found a static method, but can't use it in this context because the user passed in an instance
translator.throwError (luaState, "unknown member name " + methodName); translator.throwError (luaState, "can't pass instance to static method " + methodName);
LuaLib.lua_pushnil (luaState); LuaLib.lua_pushnil (luaState);
} }
} else {
// push false because we are NOT returning a function (see luaIndexFunction) // kevinh - we want to throw an exception because meerly returning 'nil' in this case
translator.push (luaState, false); // is not sufficient. valid data members may return nil and therefore there must be some
return 2; // way to know the member just doesn't exist.
} translator.throwError (luaState, "unknown member name " + methodName);
LuaLib.lua_pushnil (luaState);
/* }
* Checks if a MemberInfo object is cached, returning it or null.
*/ // push false because we are NOT returning a function (see luaIndexFunction)
private object checkMemberCache (Hashtable memberCache, IReflect objType, string memberName) translator.push (luaState, false);
{ return 2;
var members = (Hashtable)memberCache [objType]; }
return !members.IsNull () ? members [memberName] : null;
} /*
* Checks if a MemberInfo object is cached, returning it or null.
/* */
* Stores a MemberInfo object in the member cache. private object checkMemberCache (Hashtable memberCache, IReflect objType, string memberName)
*/ {
private void setMemberCache (Hashtable memberCache, IReflect objType, string memberName, object member) var members = (Hashtable)memberCache [objType];
{ return !members.IsNull () ? members [memberName] : null;
var members = (Hashtable)memberCache [objType]; }
if (members.IsNull ()) { /*
members = new Hashtable (); * Stores a MemberInfo object in the member cache.
memberCache [objType] = members; */
} private void setMemberCache (Hashtable memberCache, IReflect objType, string memberName, object member)
{
members [memberName] = member; var members = (Hashtable)memberCache [objType];
}
if (members.IsNull ()) {
/* members = new Hashtable ();
* __newindex metafunction of CLR objects. Receives the object, memberCache [objType] = members;
* the member name and the value to be stored as arguments. Throws }
* and error if the assignment is invalid.
*/ members [memberName] = member;
}
/*
* __newindex metafunction of CLR objects. Receives the object,
* the member name and the value to be stored as arguments. Throws
* and error if the assignment is invalid.
*/
#if MONOTOUCH #if MONOTOUCH
[MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_CFunction))] [MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_CFunction))]
#endif #endif
[System.Runtime.InteropServices.AllowReversePInvokeCalls] [System.Runtime.InteropServices.AllowReversePInvokeCalls]
private int setFieldOrProperty (LuaCore.lua_State luaState) private static int setFieldOrProperty (LuaCore.lua_State luaState)
{ {
object target = translator.getRawNetObject (luaState, 1); var translator = ObjectTranslatorPool.Instance.Find (luaState);
var instance = translator.MetaFunctionsInstance;
if (target.IsNull ()) { return instance.setFieldOrPropertyInternal (luaState);
translator.throwError (luaState, "trying to index and invalid object reference"); }
return 0;
} private int setFieldOrPropertyInternal (LuaCore.lua_State luaState)
{
var type = target.GetType (); object target = translator.getRawNetObject (luaState, 1);
// First try to look up the parameter as a property name if (target.IsNull ()) {
string detailMessage; translator.throwError (luaState, "trying to index and invalid object reference");
bool didMember = trySetMember (luaState, type, target, BindingFlags.Instance | BindingFlags.IgnoreCase, out detailMessage); return 0;
}
if (didMember)
return 0; // Must have found the property name var type = target.GetType ();
// We didn't find a property name, now see if we can use a [] style this accessor to set array contents // First try to look up the parameter as a property name
try { string detailMessage;
if (type.IsArray && LuaLib.lua_isnumber (luaState, 2)) { bool didMember = trySetMember (luaState, type, target, BindingFlags.Instance | BindingFlags.IgnoreCase, out detailMessage);
int index = (int)LuaLib.lua_tonumber (luaState, 2);
var arr = (Array)target; if (didMember)
object val = translator.getAsType (luaState, 3, arr.GetType ().GetElementType ()); return 0; // Must have found the property name
arr.SetValue (val, index);
} else { // We didn't find a property name, now see if we can use a [] style this accessor to set array contents
// Try to see if we have a this[] accessor try {
var setter = type.GetMethod ("set_Item"); if (type.IsArray && LuaLib.lua_isnumber (luaState, 2)) {
if (!setter.IsNull ()) { int index = (int)LuaLib.lua_tonumber (luaState, 2);
var args = setter.GetParameters (); var arr = (Array)target;
var valueType = args [1].ParameterType; object val = translator.getAsType (luaState, 3, arr.GetType ().GetElementType ());
arr.SetValue (val, index);
// The new val ue the user specified } else {
object val = translator.getAsType (luaState, 3, valueType); // Try to see if we have a this[] accessor
var indexType = args [0].ParameterType; var setter = type.GetMethod ("set_Item");
object index = translator.getAsType (luaState, 2, indexType); if (!setter.IsNull ()) {
var args = setter.GetParameters ();
object[] methodArgs = new object[2]; var valueType = args [1].ParameterType;
// Just call the indexer - if out of bounds an exception will happen // The new val ue the user specified
methodArgs [0] = index; object val = translator.getAsType (luaState, 3, valueType);
methodArgs [1] = val; var indexType = args [0].ParameterType;
setter.Invoke (target, methodArgs); object index = translator.getAsType (luaState, 2, indexType);
} else
translator.throwError (luaState, detailMessage); // Pass the original message from trySetMember because it is probably best object[] methodArgs = new object[2];
}
} catch (SEHException) { // Just call the indexer - if out of bounds an exception will happen
// If we are seeing a C++ exception - this must actually be for Lua's private use. Let it handle it methodArgs [0] = index;
throw; methodArgs [1] = val;
} catch (Exception e) { setter.Invoke (target, methodArgs);
ThrowError (luaState, e); } else
} translator.throwError (luaState, detailMessage); // Pass the original message from trySetMember because it is probably best
}
return 0; } catch (SEHException) {
} // If we are seeing a C++ exception - this must actually be for Lua's private use. Let it handle it
throw;
/// <summary> } catch (Exception e) {
/// Tries to set a named property or field ThrowError (luaState, e);
/// </summary> }
/// <param name="luaState"></param>
/// <param name="targetType"></param> return 0;
/// <param name="target"></param> }
/// <param name="bindingType"></param>
/// <returns>false if unable to find the named member, true for success</returns> /// <summary>
private bool trySetMember (LuaCore.lua_State luaState, IReflect targetType, object target, BindingFlags bindingType, out string detailMessage) /// Tries to set a named property or field
{ /// </summary>
detailMessage = null; // No error yet /// <param name="luaState"></param>
/// <param name="targetType"></param>
// If not already a string just return - we don't want to call tostring - which has the side effect of /// <param name="target"></param>
// changing the lua typecode to string /// <param name="bindingType"></param>
// Note: We don't use isstring because the standard lua C isstring considers either strings or numbers to /// <returns>false if unable to find the named member, true for success</returns>
// be true for isstring. private bool trySetMember (LuaCore.lua_State luaState, IReflect targetType, object target, BindingFlags bindingType, out string detailMessage)
if (LuaLib.lua_type (luaState, 2) != LuaTypes.String) { {
detailMessage = "property names must be strings"; detailMessage = null; // No error yet
return false;
} // If not already a string just return - we don't want to call tostring - which has the side effect of
// changing the lua typecode to string
// We only look up property names by string // Note: We don't use isstring because the standard lua C isstring considers either strings or numbers to
string fieldName = LuaLib.lua_tostring (luaState, 2).ToString (); // be true for isstring.
if (fieldName.IsNull () || fieldName.Length < 1 || !(char.IsLetter (fieldName [0]) || fieldName [0] == '_')) { if (LuaLib.lua_type (luaState, 2) != LuaTypes.String) {
detailMessage = "invalid property name"; detailMessage = "property names must be strings";
return false; return false;
} }
// Find our member via reflection or the cache // We only look up property names by string
var member = (MemberInfo)checkMemberCache (memberCache, targetType, fieldName); string fieldName = LuaLib.lua_tostring (luaState, 2).ToString ();
if (member.IsNull ()) { if (fieldName.IsNull () || fieldName.Length < 1 || !(char.IsLetter (fieldName [0]) || fieldName [0] == '_')) {
//CP: Removed NonPublic binding search and made case insensitive detailMessage = "invalid property name";
var members = targetType.GetMember (fieldName, bindingType | BindingFlags.Public | BindingFlags.IgnoreCase/*| BindingFlags.NonPublic*/); return false;
}
if (members.Length > 0) {
member = members [0]; // Find our member via reflection or the cache
setMemberCache (memberCache, targetType, fieldName, member); var member = (MemberInfo)checkMemberCache (memberCache, targetType, fieldName);
} else { if (member.IsNull ()) {
detailMessage = "field or property '" + fieldName + "' does not exist"; //CP: Removed NonPublic binding search and made case insensitive
return false; var members = targetType.GetMember (fieldName, bindingType | BindingFlags.Public | BindingFlags.IgnoreCase/*| BindingFlags.NonPublic*/);
}
} if (members.Length > 0) {
member = members [0];
if (member.MemberType == MemberTypes.Field) { setMemberCache (memberCache, targetType, fieldName, member);
var field = (FieldInfo)member; } else {
object val = translator.getAsType (luaState, 3, field.FieldType); detailMessage = "field or property '" + fieldName + "' does not exist";
return false;
try { }
field.SetValue (target, val); }
} catch (Exception e) {
ThrowError (luaState, e); if (member.MemberType == MemberTypes.Field) {
} var field = (FieldInfo)member;
object val = translator.getAsType (luaState, 3, field.FieldType);
// We did a call
return true; try {
} else if (member.MemberType == MemberTypes.Property) { field.SetValue (target, val);
var property = (PropertyInfo)member; } catch (Exception e) {
object val = translator.getAsType (luaState, 3, property.PropertyType); ThrowError (luaState, e);
}
try {
property.SetValue (target, val, null); // We did a call
} catch (Exception e) { return true;
ThrowError (luaState, e); } else if (member.MemberType == MemberTypes.Property) {
} var property = (PropertyInfo)member;
object val = translator.getAsType (luaState, 3, property.PropertyType);
// We did a call
return true; try {
} property.SetValue (target, val, null);
} catch (Exception e) {
detailMessage = "'" + fieldName + "' is not a .net field or property"; ThrowError (luaState, e);
return false; }
}
// We did a call
/* return true;
* Writes to fields or properties, either static or instance. Throws an error }
* if the operation is invalid.
*/ detailMessage = "'" + fieldName + "' is not a .net field or property";
private int setMember (LuaCore.lua_State luaState, IReflect targetType, object target, BindingFlags bindingType) return false;
{ }
string detail;
bool success = trySetMember (luaState, targetType, target, bindingType, out detail); /*
* Writes to fields or properties, either static or instance. Throws an error
if (!success) * if the operation is invalid.
translator.throwError (luaState, detail); */
private int setMember (LuaCore.lua_State luaState, IReflect targetType, object target, BindingFlags bindingType)
return 0; {
} string detail;
bool success = trySetMember (luaState, targetType, target, bindingType, out detail);
/// <summary>
/// Convert a C# exception into a Lua error if (!success)
/// </summary> translator.throwError (luaState, detail);
/// <param name="e"></param>
/// We try to look into the exception to give the most meaningful description return 0;
void ThrowError (LuaCore.lua_State luaState, Exception e) }
{
// If we got inside a reflection show what really happened /// <summary>
var te = e as TargetInvocationException; /// Convert a C# exception into a Lua error
/// </summary>
if (!te.IsNull ()) /// <param name="e"></param>
e = te.InnerException; /// We try to look into the exception to give the most meaningful description
void ThrowError (LuaCore.lua_State luaState, Exception e)
translator.throwError (luaState, e); {
} // If we got inside a reflection show what really happened
var te = e as TargetInvocationException;
/*
* __index metafunction of type references, works on static members. if (!te.IsNull ())
*/ e = te.InnerException;
translator.throwError (luaState, e);
}
/*
* __index metafunction of type references, works on static members.
*/
#if MONOTOUCH #if MONOTOUCH
[MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_CFunction))] [MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_CFunction))]
#endif #endif
[System.Runtime.InteropServices.AllowReversePInvokeCalls] [System.Runtime.InteropServices.AllowReversePInvokeCalls]
private int getClassMethod (LuaCore.lua_State luaState) private static int getClassMethod (LuaCore.lua_State luaState)
{ {
IReflect klass; var translator = ObjectTranslatorPool.Instance.Find (luaState);
object obj = translator.getRawNetObject (luaState, 1); var instance = translator.MetaFunctionsInstance;
return instance.getClassMethodInternal (luaState);
if (obj.IsNull () || !(obj is IReflect)) { }
translator.throwError (luaState, "trying to index an invalid type reference");
LuaLib.lua_pushnil (luaState); private int getClassMethodInternal (LuaCore.lua_State luaState)
return 1; {
} else IReflect klass;
klass = (IReflect)obj; object obj = translator.getRawNetObject (luaState, 1);
if (LuaLib.lua_isnumber (luaState, 2)) { if (obj.IsNull () || !(obj is IReflect)) {
int size = (int)LuaLib.lua_tonumber (luaState, 2); translator.throwError (luaState, "trying to index an invalid type reference");
translator.push (luaState, Array.CreateInstance (klass.UnderlyingSystemType, size)); LuaLib.lua_pushnil (luaState);
return 1; return 1;
} else { } else
string methodName = LuaLib.lua_tostring (luaState, 2).ToString (); klass = (IReflect)obj;
if (methodName.IsNull ()) { if (LuaLib.lua_isnumber (luaState, 2)) {
LuaLib.lua_pushnil (luaState); int size = (int)LuaLib.lua_tonumber (luaState, 2);
return 1; translator.push (luaState, Array.CreateInstance (klass.UnderlyingSystemType, size));
} //CP: Ignore case return 1;
else } else {
return getMember (luaState, klass, null, methodName, BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.IgnoreCase); string methodName = LuaLib.lua_tostring (luaState, 2).ToString ();
}
} if (methodName.IsNull ()) {
LuaLib.lua_pushnil (luaState);
/* return 1;
* __newindex function of type references, works on static members. } //CP: Ignore case
*/ else
return getMember (luaState, klass, null, methodName, BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.IgnoreCase);
}
}
/*
* __newindex function of type references, works on static members.
*/
#if MONOTOUCH #if MONOTOUCH
[MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_CFunction))] [MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_CFunction))]
#endif #endif
[System.Runtime.InteropServices.AllowReversePInvokeCalls] [System.Runtime.InteropServices.AllowReversePInvokeCalls]
private int setClassFieldOrProperty (LuaCore.lua_State luaState) private static int setClassFieldOrProperty (LuaCore.lua_State luaState)
{ {
IReflect target; var translator = ObjectTranslatorPool.Instance.Find (luaState);
object obj = translator.getRawNetObject (luaState, 1); var instance = translator.MetaFunctionsInstance;
return instance.setClassFieldOrPropertyInternal (luaState);
if (obj.IsNull () || !(obj is IReflect)) { }
translator.throwError (luaState, "trying to index an invalid type reference");
return 0; private int setClassFieldOrPropertyInternal (LuaCore.lua_State luaState)
} else {
target = (IReflect)obj; IReflect target;
object obj = translator.getRawNetObject (luaState, 1);
return setMember (luaState, target, null, BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.IgnoreCase);
} if (obj.IsNull () || !(obj is IReflect)) {
translator.throwError (luaState, "trying to index an invalid type reference");
/* return 0;
* __call metafunction of type references. Searches for and calls } else
* a constructor for the type. Returns nil if the constructor is not target = (IReflect)obj;
* found or if the arguments are invalid. Throws an error if the constructor
* generates an exception. return setMember (luaState, target, null, BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.IgnoreCase);
*/ }
/*
* __call metafunction of type references. Searches for and calls
* a constructor for the type. Returns nil if the constructor is not
* found or if the arguments are invalid. Throws an error if the constructor
* generates an exception.
*/
#if MONOTOUCH #if MONOTOUCH
[MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_CFunction))] [MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_CFunction))]
#endif #endif
[System.Runtime.InteropServices.AllowReversePInvokeCalls] [System.Runtime.InteropServices.AllowReversePInvokeCalls]
private int callConstructor (LuaCore.lua_State luaState) private static int callConstructor (LuaCore.lua_State luaState)
{ {
var validConstructor = new MethodCache (); var translator = ObjectTranslatorPool.Instance.Find (luaState);
IReflect klass; var instance = translator.MetaFunctionsInstance;
object obj = translator.getRawNetObject (luaState, 1); return instance.callConstructorInternal (luaState);
}
if (obj.IsNull () || !(obj is IReflect)) {
translator.throwError (luaState, "trying to call constructor on an invalid type reference"); private int callConstructorInternal (LuaCore.lua_State luaState)
LuaLib.lua_pushnil (luaState); {
return 1; var validConstructor = new MethodCache ();
} else IReflect klass;
klass = (IReflect)obj; object obj = translator.getRawNetObject (luaState, 1);
LuaLib.lua_remove (luaState, 1); if (obj.IsNull () || !(obj is IReflect)) {
var constructors = klass.UnderlyingSystemType.GetConstructors (); translator.throwError (luaState, "trying to call constructor on an invalid type reference");
LuaLib.lua_pushnil (luaState);
foreach (var constructor in constructors) { return 1;
bool isConstructor = matchParameters (luaState, constructor, ref validConstructor); } else
klass = (IReflect)obj;
if (isConstructor) {
try { LuaLib.lua_remove (luaState, 1);
translator.push (luaState, constructor.Invoke (validConstructor.args)); var constructors = klass.UnderlyingSystemType.GetConstructors ();
} catch (TargetInvocationException e) {
ThrowError (luaState, e); foreach (var constructor in constructors) {
LuaLib.lua_pushnil (luaState); bool isConstructor = matchParameters (luaState, constructor, ref validConstructor);
} catch {
LuaLib.lua_pushnil (luaState); if (isConstructor) {
} try {
translator.push (luaState, constructor.Invoke (validConstructor.args));
return 1; } catch (TargetInvocationException e) {
} ThrowError (luaState, e);
} LuaLib.lua_pushnil (luaState);
} catch {
string constructorName = (constructors.Length == 0) ? "unknown" : constructors [0].Name; LuaLib.lua_pushnil (luaState);
translator.throwError (luaState, String.Format ("{0} does not contain constructor({1}) argument match", }
klass.UnderlyingSystemType, constructorName));
LuaLib.lua_pushnil (luaState); return 1;
return 1; }
} }
/* string constructorName = (constructors.Length == 0) ? "unknown" : constructors [0].Name;
* Matches a method against its arguments in the Lua stack. Returns translator.throwError (luaState, String.Format ("{0} does not contain constructor({1}) argument match",
* if the match was succesful. It it was also returns the information klass.UnderlyingSystemType, constructorName));
* necessary to invoke the method. LuaLib.lua_pushnil (luaState);
*/ return 1;
internal bool matchParameters (LuaCore.lua_State luaState, MethodBase method, ref MethodCache methodCache) }
{
ExtractValue extractValue; /*
bool isMethod = true; * Matches a method against its arguments in the Lua stack. Returns
var paramInfo = method.GetParameters (); * if the match was succesful. It it was also returns the information
int currentLuaParam = 1; * necessary to invoke the method.
int nLuaParams = LuaLib.lua_gettop (luaState); */
var paramList = new ArrayList (); internal bool matchParameters (LuaCore.lua_State luaState, MethodBase method, ref MethodCache methodCache)
var outList = new List<int> (); {
var argTypes = new List<MethodArgs> (); ExtractValue extractValue;
bool isMethod = true;
foreach (var currentNetParam in paramInfo) { var paramInfo = method.GetParameters ();
if (!currentNetParam.IsIn && currentNetParam.IsOut) // Skips out params int currentLuaParam = 1;
outList.Add (paramList.Add (null)); int nLuaParams = LuaLib.lua_gettop (luaState);
else if (currentLuaParam > nLuaParams) { // Adds optional parameters var paramList = new ArrayList ();
if (currentNetParam.IsOptional) var outList = new List<int> ();
paramList.Add (currentNetParam.DefaultValue); var argTypes = new List<MethodArgs> ();
else {
isMethod = false; foreach (var currentNetParam in paramInfo) {
break; if (!currentNetParam.IsIn && currentNetParam.IsOut) // Skips out params
} outList.Add (paramList.Add (null));
} else if (_IsTypeCorrect (luaState, currentLuaParam, currentNetParam, out extractValue)) { // Type checking else if (currentLuaParam > nLuaParams) { // Adds optional parameters
int index = paramList.Add (extractValue (luaState, currentLuaParam)); if (currentNetParam.IsOptional)
var methodArg = new MethodArgs (); paramList.Add (currentNetParam.DefaultValue);
methodArg.index = index; else {
methodArg.extractValue = extractValue; isMethod = false;
argTypes.Add (methodArg); break;
}
if (currentNetParam.ParameterType.IsByRef) } else if (_IsTypeCorrect (luaState, currentLuaParam, currentNetParam, out extractValue)) { // Type checking
outList.Add (index); int index = paramList.Add (extractValue (luaState, currentLuaParam));
var methodArg = new MethodArgs ();
currentLuaParam++; methodArg.index = index;
} // Type does not match, ignore if the parameter is optional methodArg.extractValue = extractValue;
else if (_IsParamsArray (luaState, currentLuaParam, currentNetParam, out extractValue)) { argTypes.Add (methodArg);
object luaParamValue = extractValue (luaState, currentLuaParam);
var paramArrayType = currentNetParam.ParameterType.GetElementType (); if (currentNetParam.ParameterType.IsByRef)
Array paramArray; outList.Add (index);
if (luaParamValue is LuaTable) { currentLuaParam++;
var table = (LuaTable)luaParamValue; } // Type does not match, ignore if the parameter is optional
var tableEnumerator = table.GetEnumerator (); else if (_IsParamsArray (luaState, currentLuaParam, currentNetParam, out extractValue)) {
paramArray = Array.CreateInstance (paramArrayType, table.Values.Count); object luaParamValue = extractValue (luaState, currentLuaParam);
tableEnumerator.Reset (); var paramArrayType = currentNetParam.ParameterType.GetElementType ();
int paramArrayIndex = 0; Array paramArray;
while (tableEnumerator.MoveNext()) { if (luaParamValue is LuaTable) {
paramArray.SetValue (Convert.ChangeType (tableEnumerator.Value, currentNetParam.ParameterType.GetElementType ()), paramArrayIndex); var table = (LuaTable)luaParamValue;
paramArrayIndex++; var tableEnumerator = table.GetEnumerator ();
} paramArray = Array.CreateInstance (paramArrayType, table.Values.Count);
} else { tableEnumerator.Reset ();
paramArray = Array.CreateInstance (paramArrayType, 1); int paramArrayIndex = 0;
paramArray.SetValue (luaParamValue, 0);
} while (tableEnumerator.MoveNext()) {
paramArray.SetValue (Convert.ChangeType (tableEnumerator.Value, currentNetParam.ParameterType.GetElementType ()), paramArrayIndex);
int index = paramList.Add (paramArray); paramArrayIndex++;
var methodArg = new MethodArgs (); }
methodArg.index = index; } else {
methodArg.extractValue = extractValue; paramArray = Array.CreateInstance (paramArrayType, 1);
methodArg.isParamsArray = true; paramArray.SetValue (luaParamValue, 0);
methodArg.paramsArrayType = paramArrayType; }
argTypes.Add (methodArg);
currentLuaParam++; int index = paramList.Add (paramArray);
} else if (currentNetParam.IsOptional) var methodArg = new MethodArgs ();
paramList.Add (currentNetParam.DefaultValue); methodArg.index = index;
else { // No match methodArg.extractValue = extractValue;
isMethod = false; methodArg.isParamsArray = true;
break; methodArg.paramsArrayType = paramArrayType;
} argTypes.Add (methodArg);
} currentLuaParam++;
} else if (currentNetParam.IsOptional)
if (currentLuaParam != nLuaParams + 1) // Number of parameters does not match paramList.Add (currentNetParam.DefaultValue);
isMethod = false; else { // No match
if (isMethod) { isMethod = false;
methodCache.args = paramList.ToArray (); break;
methodCache.cachedMethod = method; }
methodCache.outList = outList.ToArray (); }
methodCache.argTypes = argTypes.ToArray ();
} if (currentLuaParam != nLuaParams + 1) // Number of parameters does not match
isMethod = false;
return isMethod; if (isMethod) {
} methodCache.args = paramList.ToArray ();
methodCache.cachedMethod = method;
/// <summary> methodCache.outList = outList.ToArray ();
/// CP: Fix for operator overloading failure methodCache.argTypes = argTypes.ToArray ();
/// Returns true if the type is set and assigns the extract value }
/// </summary>
/// <param name="luaState"></param> return isMethod;
/// <param name="currentLuaParam"></param> }
/// <param name="currentNetParam"></param>
/// <param name="extractValue"></param> /// <summary>
/// <returns></returns> /// CP: Fix for operator overloading failure
private bool _IsTypeCorrect (LuaCore.lua_State luaState, int currentLuaParam, ParameterInfo currentNetParam, out ExtractValue extractValue) /// Returns true if the type is set and assigns the extract value
{ /// </summary>
try { /// <param name="luaState"></param>
return (extractValue = translator.typeChecker.checkType (luaState, currentLuaParam, currentNetParam.ParameterType)) != null; /// <param name="currentLuaParam"></param>
} catch { /// <param name="currentNetParam"></param>
extractValue = null; /// <param name="extractValue"></param>
Debug.WriteLine ("Type wasn't correct"); /// <returns></returns>
return false; private bool _IsTypeCorrect (LuaCore.lua_State luaState, int currentLuaParam, ParameterInfo currentNetParam, out ExtractValue extractValue)
} {
} try {
return (extractValue = translator.typeChecker.checkType (luaState, currentLuaParam, currentNetParam.ParameterType)) != null;
private bool _IsParamsArray (LuaCore.lua_State luaState, int currentLuaParam, ParameterInfo currentNetParam, out ExtractValue extractValue) } catch {
{ extractValue = null;
extractValue = null; Debug.WriteLine ("Type wasn't correct");
return false;
if (currentNetParam.GetCustomAttributes (typeof(ParamArrayAttribute), false).Length > 0) { }
LuaTypes luaType; }
try { private bool _IsParamsArray (LuaCore.lua_State luaState, int currentLuaParam, ParameterInfo currentNetParam, out ExtractValue extractValue)
luaType = LuaLib.lua_type (luaState, currentLuaParam); {
} catch (Exception ex) { extractValue = null;
Debug.WriteLine ("Could not retrieve lua type while attempting to determine params Array Status.");
Debug.WriteLine (ex.Message); if (currentNetParam.GetCustomAttributes (typeof(ParamArrayAttribute), false).Length > 0) {
extractValue = null; LuaTypes luaType;
return false;
} try {
luaType = LuaLib.lua_type (luaState, currentLuaParam);
if (luaType == LuaTypes.Table) { } catch (Exception ex) {
try { Debug.WriteLine ("Could not retrieve lua type while attempting to determine params Array Status.");
extractValue = translator.typeChecker.getExtractor (typeof(LuaTable)); Debug.WriteLine (ex.Message);
} catch (Exception/* ex*/) { extractValue = null;
Debug.WriteLine ("An error occurred during an attempt to retrieve a LuaTable extractor while checking for params array status."); return false;
} }
if (!extractValue.IsNull ()) { if (luaType == LuaTypes.Table) {
return true; try {
} extractValue = translator.typeChecker.getExtractor (typeof(LuaTable));
} else { } catch (Exception/* ex*/) {
var paramElementType = currentNetParam.ParameterType.GetElementType (); Debug.WriteLine ("An error occurred during an attempt to retrieve a LuaTable extractor while checking for params array status.");
}
try {
extractValue = translator.typeChecker.checkType (luaState, currentLuaParam, paramElementType); if (!extractValue.IsNull ()) {
} catch (Exception/* ex*/) { return true;
Debug.WriteLine (string.Format ("An error occurred during an attempt to retrieve an extractor ({0}) while checking for params array status.", paramElementType.FullName)); }
} } else {
var paramElementType = currentNetParam.ParameterType.GetElementType ();
if (!extractValue.IsNull ()) {
return true; try {
} extractValue = translator.typeChecker.checkType (luaState, currentLuaParam, paramElementType);
} } catch (Exception/* ex*/) {
} Debug.WriteLine (string.Format ("An error occurred during an attempt to retrieve an extractor ({0}) while checking for params array status.", paramElementType.FullName));
}
Debug.WriteLine ("Type wasn't Params object.");
return false; if (!extractValue.IsNull ()) {
} return true;
} }
}
}
Debug.WriteLine ("Type wasn't Params object.");
return false;
}
}
} }
\ No newline at end of file
/* /*
* This file is part of LuaInterface. * This file is part of LuaInterface.
* *
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz. * Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/> * Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*/ */
using System; using System;
using System.Reflection; using System.Reflection;
using System.Collections.Generic; using System.Collections.Generic;
using LuaInterface.Exceptions; using LuaInterface.Exceptions;
using LuaInterface.Extensions; using LuaInterface.Extensions;
namespace LuaInterface.Method namespace LuaInterface.Method
{ {
using LuaCore = KeraLua.Lua; #if USE_KOPILUA
using LuaCore = KopiLua.Lua;
/* #else
* Argument extraction with type-conversion function using LuaCore = KeraLua.Lua;
*/ #endif
delegate object ExtractValue (LuaCore.lua_State luaState, int stackPos);
/*
/* * Argument extraction with type-conversion function
* Wrapper class for methods/constructors accessed from Lua. */
* delegate object ExtractValue (LuaCore.lua_State luaState, int stackPos);
* Author: Fabio Mascarenhas
* Version: 1.0 /*
*/ * Wrapper class for methods/constructors accessed from Lua.
class LuaMethodWrapper *
{ * Author: Fabio Mascarenhas
internal LuaCore.lua_CFunction invokeFunction; * Version: 1.0
private ObjectTranslator _Translator; */
private MethodBase _Method; class LuaMethodWrapper
private MethodCache _LastCalledMethod = new MethodCache (); {
private string _MethodName; internal LuaCore.lua_CFunction invokeFunction;
private MemberInfo[] _Members; private ObjectTranslator _Translator;
private ExtractValue _ExtractTarget; private MethodBase _Method;
private object _Target; private MethodCache _LastCalledMethod = new MethodCache ();
private BindingFlags _BindingType; private string _MethodName;
private MemberInfo[] _Members;
/* private ExtractValue _ExtractTarget;
* Constructs the wrapper for a known MethodBase instance private object _Target;
*/ private BindingFlags _BindingType;
public LuaMethodWrapper (ObjectTranslator translator, object target, IReflect targetType, MethodBase method)
{ /*
invokeFunction = new LuaCore.lua_CFunction (this.call); * Constructs the wrapper for a known MethodBase instance
_Translator = translator; */
_Target = target; public LuaMethodWrapper (ObjectTranslator translator, object target, IReflect targetType, MethodBase method)
{
if (!targetType.IsNull ()) invokeFunction = new LuaCore.lua_CFunction (this.call);
_ExtractTarget = translator.typeChecker.getExtractor (targetType); _Translator = translator;
_Target = target;
_Method = method;
_MethodName = method.Name; if (!targetType.IsNull ())
_ExtractTarget = translator.typeChecker.getExtractor (targetType);
if (method.IsStatic)
_BindingType = BindingFlags.Static; _Method = method;
else _MethodName = method.Name;
_BindingType = BindingFlags.Instance;
} if (method.IsStatic)
_BindingType = BindingFlags.Static;
/* else
* Constructs the wrapper for a known method name _BindingType = BindingFlags.Instance;
*/ }
public LuaMethodWrapper (ObjectTranslator translator, IReflect targetType, string methodName, BindingFlags bindingType)
{ /*
invokeFunction = new LuaCore.lua_CFunction (this.call); * Constructs the wrapper for a known method name
*/
_Translator = translator; public LuaMethodWrapper (ObjectTranslator translator, IReflect targetType, string methodName, BindingFlags bindingType)
_MethodName = methodName; {
invokeFunction = new LuaCore.lua_CFunction (this.call);
if (!targetType.IsNull ())
_ExtractTarget = translator.typeChecker.getExtractor (targetType); _Translator = translator;
_MethodName = methodName;
_BindingType = bindingType;
//CP: Removed NonPublic binding search and added IgnoreCase if (!targetType.IsNull ())
_Members = targetType.UnderlyingSystemType.GetMember (methodName, MemberTypes.Method, bindingType | BindingFlags.Public | BindingFlags.IgnoreCase/*|BindingFlags.NonPublic*/); _ExtractTarget = translator.typeChecker.getExtractor (targetType);
}
_BindingType = bindingType;
/// <summary> //CP: Removed NonPublic binding search and added IgnoreCase
/// Convert C# exceptions into Lua errors _Members = targetType.UnderlyingSystemType.GetMember (methodName, MemberTypes.Method, bindingType | BindingFlags.Public | BindingFlags.IgnoreCase/*|BindingFlags.NonPublic*/);
/// </summary> }
/// <returns>num of things on stack</returns>
/// <param name="e">null for no pending exception</param> /// <summary>
int SetPendingException (Exception e) /// Convert C# exceptions into Lua errors
{ /// </summary>
return _Translator.interpreter.SetPendingException (e); /// <returns>num of things on stack</returns>
} /// <param name="e">null for no pending exception</param>
int SetPendingException (Exception e)
/* {
* Calls the method. Receives the arguments from the Lua stack return _Translator.interpreter.SetPendingException (e);
* and returns values in it. }
*/
#if MONOTOUCH /*
[MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_CFunction))] * Calls the method. Receives the arguments from the Lua stack
#endif * and returns values in it.
[System.Runtime.InteropServices.AllowReversePInvokeCalls] */
int call (LuaCore.lua_State luaState) int call (LuaCore.lua_State luaState)
{ {
var methodToCall = _Method; var methodToCall = _Method;
object targetObject = _Target; object targetObject = _Target;
bool failedCall = true; bool failedCall = true;
int nReturnValues = 0; int nReturnValues = 0;
if (!LuaLib.lua_checkstack (luaState, 5)) if (!LuaLib.lua_checkstack (luaState, 5))
throw new LuaException ("Lua stack overflow"); throw new LuaException ("Lua stack overflow");
bool isStatic = (_BindingType & BindingFlags.Static) == BindingFlags.Static; bool isStatic = (_BindingType & BindingFlags.Static) == BindingFlags.Static;
SetPendingException (null); SetPendingException (null);
if (methodToCall.IsNull ()) { // Method from name if (methodToCall.IsNull ()) { // Method from name
if (isStatic) if (isStatic)
targetObject = null; targetObject = null;
else else
targetObject = _ExtractTarget (luaState, 1); targetObject = _ExtractTarget (luaState, 1);
//LuaLib.lua_remove(luaState,1); // Pops the receiver //LuaLib.lua_remove(luaState,1); // Pops the receiver
if (!_LastCalledMethod.cachedMethod.IsNull ()) { // Cached? if (!_LastCalledMethod.cachedMethod.IsNull ()) { // Cached?
int numStackToSkip = isStatic ? 0 : 1; // If this is an instance invoe we will have an extra arg on the stack for the targetObject 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 = LuaLib.lua_gettop (luaState) - numStackToSkip; int numArgsPassed = LuaLib.lua_gettop (luaState) - numStackToSkip;
if (numArgsPassed == _LastCalledMethod.argTypes.Length) { // No. of args match? if (numArgsPassed == _LastCalledMethod.argTypes.Length) { // No. of args match?
if (!LuaLib.lua_checkstack (luaState, _LastCalledMethod.outList.Length + 6)) if (!LuaLib.lua_checkstack (luaState, _LastCalledMethod.outList.Length + 6))
throw new LuaException ("Lua stack overflow"); throw new LuaException ("Lua stack overflow");
try { try {
for (int i = 0; i < _LastCalledMethod.argTypes.Length; i++) { for (int i = 0; i < _LastCalledMethod.argTypes.Length; i++) {
if (_LastCalledMethod.argTypes [i].isParamsArray) { if (_LastCalledMethod.argTypes [i].isParamsArray) {
object luaParamValue = _LastCalledMethod.argTypes [i].extractValue (luaState, i + 1 + numStackToSkip); object luaParamValue = _LastCalledMethod.argTypes [i].extractValue (luaState, i + 1 + numStackToSkip);
var paramArrayType = _LastCalledMethod.argTypes [i].paramsArrayType; var paramArrayType = _LastCalledMethod.argTypes [i].paramsArrayType;
Array paramArray; Array paramArray;
if (luaParamValue is LuaTable) { if (luaParamValue is LuaTable) {
var table = (LuaTable)luaParamValue; var table = (LuaTable)luaParamValue;
paramArray = Array.CreateInstance (paramArrayType, table.Values.Count); paramArray = Array.CreateInstance (paramArrayType, table.Values.Count);
for (int x = 1; x <= table.Values.Count; x++) for (int x = 1; x <= table.Values.Count; x++)
paramArray.SetValue (Convert.ChangeType (table [x], paramArrayType), x - 1); paramArray.SetValue (Convert.ChangeType (table [x], paramArrayType), x - 1);
} else { } else {
paramArray = Array.CreateInstance (paramArrayType, 1); paramArray = Array.CreateInstance (paramArrayType, 1);
paramArray.SetValue (luaParamValue, 0); paramArray.SetValue (luaParamValue, 0);
} }
_LastCalledMethod.args [_LastCalledMethod.argTypes [i].index] = paramArray; _LastCalledMethod.args [_LastCalledMethod.argTypes [i].index] = paramArray;
} else { } else {
_LastCalledMethod.args [_LastCalledMethod.argTypes [i].index] = _LastCalledMethod.args [_LastCalledMethod.argTypes [i].index] =
_LastCalledMethod.argTypes [i].extractValue (luaState, i + 1 + numStackToSkip); _LastCalledMethod.argTypes [i].extractValue (luaState, i + 1 + numStackToSkip);
} }
if (_LastCalledMethod.args [_LastCalledMethod.argTypes [i].index] == null && if (_LastCalledMethod.args [_LastCalledMethod.argTypes [i].index] == null &&
!LuaLib.lua_isnil (luaState, i + 1 + numStackToSkip)) !LuaLib.lua_isnil (luaState, i + 1 + numStackToSkip))
throw new LuaException ("argument number " + (i + 1) + " is invalid"); throw new LuaException ("argument number " + (i + 1) + " is invalid");
} }
if ((_BindingType & BindingFlags.Static) == BindingFlags.Static) if ((_BindingType & BindingFlags.Static) == BindingFlags.Static)
_Translator.push (luaState, _LastCalledMethod.cachedMethod.Invoke (null, _LastCalledMethod.args)); _Translator.push (luaState, _LastCalledMethod.cachedMethod.Invoke (null, _LastCalledMethod.args));
else { else {
if (_LastCalledMethod.cachedMethod.IsConstructor) if (_LastCalledMethod.cachedMethod.IsConstructor)
_Translator.push (luaState, ((ConstructorInfo)_LastCalledMethod.cachedMethod).Invoke (_LastCalledMethod.args)); _Translator.push (luaState, ((ConstructorInfo)_LastCalledMethod.cachedMethod).Invoke (_LastCalledMethod.args));
else else
_Translator.push (luaState, _LastCalledMethod.cachedMethod.Invoke (targetObject, _LastCalledMethod.args)); _Translator.push (luaState, _LastCalledMethod.cachedMethod.Invoke (targetObject, _LastCalledMethod.args));
} }
failedCall = false; failedCall = false;
} catch (TargetInvocationException e) { } catch (TargetInvocationException e) {
// Failure of method invocation // Failure of method invocation
return SetPendingException (e.GetBaseException ()); return SetPendingException (e.GetBaseException ());
} catch (Exception e) { } catch (Exception e) {
if (_Members.Length == 1) // Is the method overloaded? if (_Members.Length == 1) // Is the method overloaded?
// No, throw error // No, throw error
return SetPendingException (e); return SetPendingException (e);
} }
} }
} }
// Cache miss // Cache miss
if (failedCall) { if (failedCall) {
// System.Diagnostics.Debug.WriteLine("cache miss on " + methodName); // System.Diagnostics.Debug.WriteLine("cache miss on " + methodName);
// If we are running an instance variable, we can now pop the targetObject from the stack // If we are running an instance variable, we can now pop the targetObject from the stack
if (!isStatic) { if (!isStatic) {
if (targetObject.IsNull ()) { if (targetObject.IsNull ()) {
_Translator.throwError (luaState, String.Format ("instance method '{0}' requires a non null target object", _MethodName)); _Translator.throwError (luaState, String.Format ("instance method '{0}' requires a non null target object", _MethodName));
LuaLib.lua_pushnil (luaState); LuaLib.lua_pushnil (luaState);
return 1; return 1;
} }
LuaLib.lua_remove (luaState, 1); // Pops the receiver LuaLib.lua_remove (luaState, 1); // Pops the receiver
} }
bool hasMatch = false; bool hasMatch = false;
string candidateName = null; string candidateName = null;
foreach (var member in _Members) { foreach (var member in _Members) {
candidateName = member.ReflectedType.Name + "." + member.Name; candidateName = member.ReflectedType.Name + "." + member.Name;
var m = (MethodInfo)member; var m = (MethodInfo)member;
bool isMethod = _Translator.matchParameters (luaState, m, ref _LastCalledMethod); bool isMethod = _Translator.matchParameters (luaState, m, ref _LastCalledMethod);
if (isMethod) { if (isMethod) {
hasMatch = true; hasMatch = true;
break; break;
} }
} }
if (!hasMatch) { if (!hasMatch) {
string msg = (candidateName == null) ? "invalid arguments to method call" : ("invalid arguments to method: " + candidateName); string msg = (candidateName == null) ? "invalid arguments to method call" : ("invalid arguments to method: " + candidateName);
_Translator.throwError (luaState, msg); _Translator.throwError (luaState, msg);
LuaLib.lua_pushnil (luaState); LuaLib.lua_pushnil (luaState);
return 1; return 1;
} }
} }
} else { // Method from MethodBase instance } else { // Method from MethodBase instance
if (methodToCall.ContainsGenericParameters) { if (methodToCall.ContainsGenericParameters) {
/*bool isMethod = */ /*bool isMethod = */
_Translator.matchParameters (luaState, methodToCall, ref _LastCalledMethod); _Translator.matchParameters (luaState, methodToCall, ref _LastCalledMethod);
if (methodToCall.IsGenericMethodDefinition) { if (methodToCall.IsGenericMethodDefinition) {
//need to make a concrete type of the generic method definition //need to make a concrete type of the generic method definition
var typeArgs = new List<Type> (); var typeArgs = new List<Type> ();
foreach (object arg in _LastCalledMethod.args) foreach (object arg in _LastCalledMethod.args)
typeArgs.Add (arg.GetType ()); typeArgs.Add (arg.GetType ());
var concreteMethod = (methodToCall as MethodInfo).MakeGenericMethod (typeArgs.ToArray ()); var concreteMethod = (methodToCall as MethodInfo).MakeGenericMethod (typeArgs.ToArray ());
_Translator.push (luaState, concreteMethod.Invoke (targetObject, _LastCalledMethod.args)); _Translator.push (luaState, concreteMethod.Invoke (targetObject, _LastCalledMethod.args));
failedCall = false; failedCall = false;
} else if (methodToCall.ContainsGenericParameters) { } else if (methodToCall.ContainsGenericParameters) {
_Translator.throwError (luaState, "unable to invoke method on generic class as the current method is an open generic method"); _Translator.throwError (luaState, "unable to invoke method on generic class as the current method is an open generic method");
LuaLib.lua_pushnil (luaState); LuaLib.lua_pushnil (luaState);
return 1; return 1;
} }
} else { } else {
if (!methodToCall.IsStatic && !methodToCall.IsConstructor && targetObject == null) { if (!methodToCall.IsStatic && !methodToCall.IsConstructor && targetObject == null) {
targetObject = _ExtractTarget (luaState, 1); targetObject = _ExtractTarget (luaState, 1);
LuaLib.lua_remove (luaState, 1); // Pops the receiver LuaLib.lua_remove (luaState, 1); // Pops the receiver
} }
if (!_Translator.matchParameters (luaState, methodToCall, ref _LastCalledMethod)) { if (!_Translator.matchParameters (luaState, methodToCall, ref _LastCalledMethod)) {
_Translator.throwError (luaState, "invalid arguments to method call"); _Translator.throwError (luaState, "invalid arguments to method call");
LuaLib.lua_pushnil (luaState); LuaLib.lua_pushnil (luaState);
return 1; return 1;
} }
} }
} }
if (failedCall) { if (failedCall) {
if (!LuaLib.lua_checkstack (luaState, _LastCalledMethod.outList.Length + 6)) if (!LuaLib.lua_checkstack (luaState, _LastCalledMethod.outList.Length + 6))
throw new LuaException ("Lua stack overflow"); throw new LuaException ("Lua stack overflow");
try { try {
if (isStatic) if (isStatic)
_Translator.push (luaState, _LastCalledMethod.cachedMethod.Invoke (null, _LastCalledMethod.args)); _Translator.push (luaState, _LastCalledMethod.cachedMethod.Invoke (null, _LastCalledMethod.args));
else { else {
if (_LastCalledMethod.cachedMethod.IsConstructor) if (_LastCalledMethod.cachedMethod.IsConstructor)
_Translator.push (luaState, ((ConstructorInfo)_LastCalledMethod.cachedMethod).Invoke (_LastCalledMethod.args)); _Translator.push (luaState, ((ConstructorInfo)_LastCalledMethod.cachedMethod).Invoke (_LastCalledMethod.args));
else else
_Translator.push (luaState, _LastCalledMethod.cachedMethod.Invoke (targetObject, _LastCalledMethod.args)); _Translator.push (luaState, _LastCalledMethod.cachedMethod.Invoke (targetObject, _LastCalledMethod.args));
} }
} catch (TargetInvocationException e) { } catch (TargetInvocationException e) {
return SetPendingException (e.GetBaseException ()); return SetPendingException (e.GetBaseException ());
} catch (Exception e) { } catch (Exception e) {
return SetPendingException (e); return SetPendingException (e);
} }
} }
// Pushes out and ref return values // Pushes out and ref return values
for (int index = 0; index < _LastCalledMethod.outList.Length; index++) { for (int index = 0; index < _LastCalledMethod.outList.Length; index++) {
nReturnValues++; nReturnValues++;
//for(int i=0;i<lastCalledMethod.outList.Length;i++) //for(int i=0;i<lastCalledMethod.outList.Length;i++)
_Translator.push (luaState, _LastCalledMethod.args [_LastCalledMethod.outList [index]]); _Translator.push (luaState, _LastCalledMethod.args [_LastCalledMethod.outList [index]]);
} }
//by isSingle 2010-09-10 11:26:31 //by isSingle 2010-09-10 11:26:31
//Desc: //Desc:
// if not return void,we need add 1, // if not return void,we need add 1,
// or we will lost the function's return value // or we will lost the function's return value
// when call dotnet function like "int foo(arg1,out arg2,out arg3)" in lua code // when call dotnet function like "int foo(arg1,out arg2,out arg3)" in lua code
if (!_LastCalledMethod.IsReturnVoid && nReturnValues > 0) if (!_LastCalledMethod.IsReturnVoid && nReturnValues > 0)
nReturnValues++; nReturnValues++;
return nReturnValues < 1 ? 1 : nReturnValues; return nReturnValues < 1 ? 1 : nReturnValues;
} }
} }
} }
\ No newline at end of file
/* /*
* This file is part of LuaInterface. * This file is part of LuaInterface.
* *
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz. * Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/> * Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*/ */
using System; using System;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using System.Diagnostics; using System.Diagnostics;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using LuaInterface.Method; using LuaInterface.Method;
using LuaInterface.Exceptions; using LuaInterface.Exceptions;
using LuaInterface.Extensions; using LuaInterface.Extensions;
namespace LuaInterface namespace LuaInterface
{ {
using LuaCore = KeraLua.Lua; #if USE_KOPILUA
using LuaCore = KopiLua.Lua;
/* #else
* Passes objects from the CLR to Lua and vice-versa using LuaCore = KeraLua.Lua;
* #endif
* Author: Fabio Mascarenhas
* Version: 1.0 /*
*/ * Passes objects from the CLR to Lua and vice-versa
public class ObjectTranslator *
{ * Author: Fabio Mascarenhas
private LuaCore.lua_CFunction registerTableFunction, unregisterTableFunction, getMethodSigFunction, * Version: 1.0
getConstructorSigFunction, importTypeFunction, loadAssemblyFunction; */
// object to object # public class ObjectTranslator
public readonly Dictionary<object, int> objectsBackMap = new Dictionary<object, int> (); {
// object # to object (FIXME - it should be possible to get object address as an object #) private LuaCore.lua_CFunction registerTableFunction, unregisterTableFunction, getMethodSigFunction,
public readonly Dictionary<int, object> objects = new Dictionary<int, object> (); getConstructorSigFunction, importTypeFunction, loadAssemblyFunction;
internal EventHandlerContainer pendingEvents = new EventHandlerContainer (); // object to object #
private MetaFunctions metaFunctions; public readonly Dictionary<object, int> objectsBackMap = new Dictionary<object, int> ();
private List<Assembly> assemblies; // object # to object (FIXME - it should be possible to get object address as an object #)
internal CheckType typeChecker; public readonly Dictionary<int, object> objects = new Dictionary<int, object> ();
internal Lua interpreter; internal EventHandlerContainer pendingEvents = new EventHandlerContainer ();
/// <summary> private MetaFunctions metaFunctions;
/// We want to ensure that objects always have a unique ID private List<Assembly> assemblies;
/// </summary> internal CheckType typeChecker;
private int nextObj = 0; internal Lua interpreter;
/// <summary>
public ObjectTranslator (Lua interpreter, LuaCore.lua_State luaState) /// We want to ensure that objects always have a unique ID
{ /// </summary>
this.interpreter = interpreter; private int nextObj = 0;
typeChecker = new CheckType (this);
metaFunctions = new MetaFunctions (this); public MetaFunctions MetaFunctionsInstance {
assemblies = new List<Assembly> (); get {
return metaFunctions;
importTypeFunction = new LuaCore.lua_CFunction (this.importType); }
loadAssemblyFunction = new LuaCore.lua_CFunction (this.loadAssembly); }
registerTableFunction = new LuaCore.lua_CFunction (this.registerTable);
unregisterTableFunction = new LuaCore.lua_CFunction (this.unregisterTable); public Lua Interpreter {
getMethodSigFunction = new LuaCore.lua_CFunction (this.getMethodSignature); get {
getConstructorSigFunction = new LuaCore.lua_CFunction (this.getConstructorSignature); return interpreter;
}
createLuaObjectList (luaState); }
createIndexingMetaFunction (luaState);
createBaseClassMetatable (luaState); public ObjectTranslator (Lua interpreter, LuaCore.lua_State luaState)
createClassMetatable (luaState); {
createFunctionMetatable (luaState); this.interpreter = interpreter;
setGlobalFunctions (luaState); typeChecker = new CheckType (this);
} metaFunctions = new MetaFunctions (this);
assemblies = new List<Assembly> ();
/*
* Sets up the list of objects in the Lua side importTypeFunction = new LuaCore.lua_CFunction (ObjectTranslator.importType);
*/ loadAssemblyFunction = new LuaCore.lua_CFunction (ObjectTranslator.loadAssembly);
private void createLuaObjectList (LuaCore.lua_State luaState) registerTableFunction = new LuaCore.lua_CFunction (ObjectTranslator.registerTable);
{ unregisterTableFunction = new LuaCore.lua_CFunction (ObjectTranslator.unregisterTable);
LuaLib.lua_pushstring (luaState, "luaNet_objects"); getMethodSigFunction = new LuaCore.lua_CFunction (ObjectTranslator.getMethodSignature);
LuaLib.lua_newtable (luaState); getConstructorSigFunction = new LuaCore.lua_CFunction (ObjectTranslator.getConstructorSignature);
LuaLib.lua_newtable (luaState);
LuaLib.lua_pushstring (luaState, "__mode"); createLuaObjectList (luaState);
LuaLib.lua_pushstring (luaState, "v"); createIndexingMetaFunction (luaState);
LuaLib.lua_settable (luaState, -3); createBaseClassMetatable (luaState);
LuaLib.lua_setmetatable (luaState, -2); createClassMetatable (luaState);
LuaLib.lua_settable (luaState, (int)LuaIndexes.Registry); createFunctionMetatable (luaState);
} setGlobalFunctions (luaState);
}
/*
* Registers the indexing function of CLR objects /*
* passed to Lua * Sets up the list of objects in the Lua side
*/ */
private void createIndexingMetaFunction (LuaCore.lua_State luaState) private void createLuaObjectList (LuaCore.lua_State luaState)
{ {
LuaLib.lua_pushstring (luaState, "luaNet_indexfunction"); LuaLib.lua_pushstring (luaState, "luaNet_objects");
LuaLib.luaL_dostring (luaState, MetaFunctions.luaIndexFunction); // steffenj: lua_dostring renamed to luaL_dostring LuaLib.lua_newtable (luaState);
//LuaLib.lua_pushstdcallcfunction(luaState, indexFunction); LuaLib.lua_newtable (luaState);
LuaLib.lua_rawset (luaState, (int)LuaIndexes.Registry); LuaLib.lua_pushstring (luaState, "__mode");
} LuaLib.lua_pushstring (luaState, "v");
LuaLib.lua_settable (luaState, -3);
/* LuaLib.lua_setmetatable (luaState, -2);
* Creates the metatable for superclasses (the base LuaLib.lua_settable (luaState, (int)LuaIndexes.Registry);
* field of registered tables) }
*/
private void createBaseClassMetatable (LuaCore.lua_State luaState) /*
{ * Registers the indexing function of CLR objects
LuaLib.luaL_newmetatable (luaState, "luaNet_searchbase"); * passed to Lua
LuaLib.lua_pushstring (luaState, "__gc"); */
LuaLib.lua_pushstdcallcfunction (luaState, metaFunctions.gcFunction); private void createIndexingMetaFunction (LuaCore.lua_State luaState)
LuaLib.lua_settable (luaState, -3); {
LuaLib.lua_pushstring (luaState, "__tostring"); LuaLib.lua_pushstring (luaState, "luaNet_indexfunction");
LuaLib.lua_pushstdcallcfunction (luaState, metaFunctions.toStringFunction); LuaLib.luaL_dostring (luaState, MetaFunctions.luaIndexFunction); // steffenj: lua_dostring renamed to luaL_dostring
LuaLib.lua_settable (luaState, -3); //LuaLib.lua_pushstdcallcfunction(luaState, indexFunction);
LuaLib.lua_pushstring (luaState, "__index"); LuaLib.lua_rawset (luaState, (int)LuaIndexes.Registry);
LuaLib.lua_pushstdcallcfunction (luaState, metaFunctions.baseIndexFunction); }
LuaLib.lua_settable (luaState, -3);
LuaLib.lua_pushstring (luaState, "__newindex"); /*
LuaLib.lua_pushstdcallcfunction (luaState, metaFunctions.newindexFunction); * Creates the metatable for superclasses (the base
LuaLib.lua_settable (luaState, -3); * field of registered tables)
LuaLib.lua_settop (luaState, -2); */
} private void createBaseClassMetatable (LuaCore.lua_State luaState)
{
/* LuaLib.luaL_newmetatable (luaState, "luaNet_searchbase");
* Creates the metatable for type references LuaLib.lua_pushstring (luaState, "__gc");
*/ LuaLib.lua_pushstdcallcfunction (luaState, metaFunctions.gcFunction);
private void createClassMetatable (LuaCore.lua_State luaState) LuaLib.lua_settable (luaState, -3);
{ LuaLib.lua_pushstring (luaState, "__tostring");
LuaLib.luaL_newmetatable (luaState, "luaNet_class"); LuaLib.lua_pushstdcallcfunction (luaState, metaFunctions.toStringFunction);
LuaLib.lua_pushstring (luaState, "__gc"); LuaLib.lua_settable (luaState, -3);
LuaLib.lua_pushstdcallcfunction (luaState, metaFunctions.gcFunction); LuaLib.lua_pushstring (luaState, "__index");
LuaLib.lua_settable (luaState, -3); LuaLib.lua_pushstdcallcfunction (luaState, metaFunctions.baseIndexFunction);
LuaLib.lua_pushstring (luaState, "__tostring"); LuaLib.lua_settable (luaState, -3);
LuaLib.lua_pushstdcallcfunction (luaState, metaFunctions.toStringFunction); LuaLib.lua_pushstring (luaState, "__newindex");
LuaLib.lua_settable (luaState, -3); LuaLib.lua_pushstdcallcfunction (luaState, metaFunctions.newindexFunction);
LuaLib.lua_pushstring (luaState, "__index"); LuaLib.lua_settable (luaState, -3);
LuaLib.lua_pushstdcallcfunction (luaState, metaFunctions.classIndexFunction); LuaLib.lua_settop (luaState, -2);
LuaLib.lua_settable (luaState, -3); }
LuaLib.lua_pushstring (luaState, "__newindex");
LuaLib.lua_pushstdcallcfunction (luaState, metaFunctions.classNewindexFunction); /*
LuaLib.lua_settable (luaState, -3); * Creates the metatable for type references
LuaLib.lua_pushstring (luaState, "__call"); */
LuaLib.lua_pushstdcallcfunction (luaState, metaFunctions.callConstructorFunction); private void createClassMetatable (LuaCore.lua_State luaState)
LuaLib.lua_settable (luaState, -3); {
LuaLib.lua_settop (luaState, -2); LuaLib.luaL_newmetatable (luaState, "luaNet_class");
} LuaLib.lua_pushstring (luaState, "__gc");
LuaLib.lua_pushstdcallcfunction (luaState, metaFunctions.gcFunction);
/* LuaLib.lua_settable (luaState, -3);
* Registers the global functions used by LuaInterface LuaLib.lua_pushstring (luaState, "__tostring");
*/ LuaLib.lua_pushstdcallcfunction (luaState, metaFunctions.toStringFunction);
private void setGlobalFunctions (LuaCore.lua_State luaState) LuaLib.lua_settable (luaState, -3);
{ LuaLib.lua_pushstring (luaState, "__index");
LuaLib.lua_pushstdcallcfunction (luaState, metaFunctions.indexFunction); LuaLib.lua_pushstdcallcfunction (luaState, metaFunctions.classIndexFunction);
LuaLib.lua_setglobal (luaState, "get_object_member"); LuaLib.lua_settable (luaState, -3);
LuaLib.lua_pushstdcallcfunction (luaState, importTypeFunction); LuaLib.lua_pushstring (luaState, "__newindex");
LuaLib.lua_setglobal (luaState, "import_type"); LuaLib.lua_pushstdcallcfunction (luaState, metaFunctions.classNewindexFunction);
LuaLib.lua_pushstdcallcfunction (luaState, loadAssemblyFunction); LuaLib.lua_settable (luaState, -3);
LuaLib.lua_setglobal (luaState, "load_assembly"); LuaLib.lua_pushstring (luaState, "__call");
LuaLib.lua_pushstdcallcfunction (luaState, registerTableFunction); LuaLib.lua_pushstdcallcfunction (luaState, metaFunctions.callConstructorFunction);
LuaLib.lua_setglobal (luaState, "make_object"); LuaLib.lua_settable (luaState, -3);
LuaLib.lua_pushstdcallcfunction (luaState, unregisterTableFunction); LuaLib.lua_settop (luaState, -2);
LuaLib.lua_setglobal (luaState, "free_object"); }
LuaLib.lua_pushstdcallcfunction (luaState, getMethodSigFunction);
LuaLib.lua_setglobal (luaState, "get_method_bysig"); /*
LuaLib.lua_pushstdcallcfunction (luaState, getConstructorSigFunction); * Registers the global functions used by LuaInterface
LuaLib.lua_setglobal (luaState, "get_constructor_bysig"); */
} private void setGlobalFunctions (LuaCore.lua_State luaState)
{
/* LuaLib.lua_pushstdcallcfunction (luaState, metaFunctions.indexFunction);
* Creates the metatable for delegates LuaLib.lua_setglobal (luaState, "get_object_member");
*/ LuaLib.lua_pushstdcallcfunction (luaState, importTypeFunction);
private void createFunctionMetatable (LuaCore.lua_State luaState) LuaLib.lua_setglobal (luaState, "import_type");
{ LuaLib.lua_pushstdcallcfunction (luaState, loadAssemblyFunction);
LuaLib.luaL_newmetatable (luaState, "luaNet_function"); LuaLib.lua_setglobal (luaState, "load_assembly");
LuaLib.lua_pushstring (luaState, "__gc"); LuaLib.lua_pushstdcallcfunction (luaState, registerTableFunction);
LuaLib.lua_pushstdcallcfunction (luaState, metaFunctions.gcFunction); LuaLib.lua_setglobal (luaState, "make_object");
LuaLib.lua_settable (luaState, -3); LuaLib.lua_pushstdcallcfunction (luaState, unregisterTableFunction);
LuaLib.lua_pushstring (luaState, "__call"); LuaLib.lua_setglobal (luaState, "free_object");
LuaLib.lua_pushstdcallcfunction (luaState, metaFunctions.execDelegateFunction); LuaLib.lua_pushstdcallcfunction (luaState, getMethodSigFunction);
LuaLib.lua_settable (luaState, -3); LuaLib.lua_setglobal (luaState, "get_method_bysig");
LuaLib.lua_settop (luaState, -2); LuaLib.lua_pushstdcallcfunction (luaState, getConstructorSigFunction);
} LuaLib.lua_setglobal (luaState, "get_constructor_bysig");
}
/*
* Passes errors (argument e) to the Lua interpreter /*
*/ * Creates the metatable for delegates
internal void throwError (LuaCore.lua_State luaState, object e) */
{ private void createFunctionMetatable (LuaCore.lua_State luaState)
// We use this to remove anything pushed by luaL_where {
int oldTop = LuaLib.lua_gettop (luaState); LuaLib.luaL_newmetatable (luaState, "luaNet_function");
LuaLib.lua_pushstring (luaState, "__gc");
// Stack frame #1 is our C# wrapper, so not very interesting to the user LuaLib.lua_pushstdcallcfunction (luaState, metaFunctions.gcFunction);
// Stack frame #2 must be the lua code that called us, so that's what we want to use LuaLib.lua_settable (luaState, -3);
LuaLib.luaL_where (luaState, 1); LuaLib.lua_pushstring (luaState, "__call");
var curlev = popValues (luaState, oldTop); LuaLib.lua_pushstdcallcfunction (luaState, metaFunctions.execDelegateFunction);
LuaLib.lua_settable (luaState, -3);
// Determine the position in the script where the exception was triggered LuaLib.lua_settop (luaState, -2);
string errLocation = string.Empty; }
if (curlev.Length > 0) /*
errLocation = curlev [0].ToString (); * Passes errors (argument e) to the Lua interpreter
*/
string message = e as string; internal void throwError (LuaCore.lua_State luaState, object e)
{
if (!message.IsNull ()) { // We use this to remove anything pushed by luaL_where
// Wrap Lua error (just a string) and store the error location int oldTop = LuaLib.lua_gettop (luaState);
e = new LuaScriptException (message, errLocation);
} else { // Stack frame #1 is our C# wrapper, so not very interesting to the user
var ex = e as Exception; // Stack frame #2 must be the lua code that called us, so that's what we want to use
LuaLib.luaL_where (luaState, 1);
if (!ex.IsNull ()) { var curlev = popValues (luaState, oldTop);
// Wrap generic .NET exception as an InnerException and store the error location
e = new LuaScriptException (ex, errLocation); // Determine the position in the script where the exception was triggered
} string errLocation = string.Empty;
}
if (curlev.Length > 0)
push (luaState, e); errLocation = curlev [0].ToString ();
LuaLib.lua_error (luaState);
} string message = e as string;
/* if (!message.IsNull ()) {
* Implementation of load_assembly. Throws an error // Wrap Lua error (just a string) and store the error location
* if the assembly is not found. e = new LuaScriptException (message, errLocation);
*/ } else {
var ex = e as Exception;
if (!ex.IsNull ()) {
// Wrap generic .NET exception as an InnerException and store the error location
e = new LuaScriptException (ex, errLocation);
}
}
push (luaState, e);
LuaLib.lua_error (luaState);
}
/*
* Implementation of load_assembly. Throws an error
* if the assembly is not found.
*/
#if MONOTOUCH #if MONOTOUCH
[MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_CFunction))] [MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_CFunction))]
#endif #endif
[System.Runtime.InteropServices.AllowReversePInvokeCalls] [System.Runtime.InteropServices.AllowReversePInvokeCalls]
private int loadAssembly (LuaCore.lua_State luaState) private static int loadAssembly (LuaCore.lua_State luaState)
{ {
try { var translator = ObjectTranslatorPool.Instance.Find (luaState);
string assemblyName = LuaLib.lua_tostring (luaState, 1).ToString (); return translator.loadAssemblyInternal (luaState);
Assembly assembly = null; }
try { private int loadAssemblyInternal (LuaCore.lua_State luaState)
assembly = Assembly.Load (assemblyName); {
} catch (BadImageFormatException) { try {
// The assemblyName was invalid. It is most likely a path. string assemblyName = LuaLib.lua_tostring (luaState, 1).ToString ();
} Assembly assembly = null;
if (assembly.IsNull ()) try {
assembly = Assembly.Load (AssemblyName.GetAssemblyName (assemblyName)); assembly = Assembly.Load (assemblyName);
} catch (BadImageFormatException) {
if (!assembly.IsNull () && !assemblies.Contains (assembly)) // The assemblyName was invalid. It is most likely a path.
assemblies.Add (assembly); }
} catch (Exception e) {
throwError (luaState, e); if (assembly.IsNull ())
} assembly = Assembly.Load (AssemblyName.GetAssemblyName (assemblyName));
return 0; if (!assembly.IsNull () && !assemblies.Contains (assembly))
} assemblies.Add (assembly);
} catch (Exception e) {
internal Type FindType (string className) throwError (luaState, e);
{ }
foreach (var assembly in assemblies) {
var klass = assembly.GetType (className); return 0;
}
if (!klass.IsNull ())
return klass; internal Type FindType (string className)
} {
return null; foreach (var assembly in assemblies) {
} var klass = assembly.GetType (className);
/* if (!klass.IsNull ())
* Implementation of import_type. Returns nil if the return klass;
* type is not found. }
*/ return null;
}
/*
* Implementation of import_type. Returns nil if the
* type is not found.
*/
#if MONOTOUCH #if MONOTOUCH
[MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_CFunction))] [MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_CFunction))]
#endif #endif
[System.Runtime.InteropServices.AllowReversePInvokeCalls] [System.Runtime.InteropServices.AllowReversePInvokeCalls]
private int importType (LuaCore.lua_State luaState) private static int importType (LuaCore.lua_State luaState)
{ {
string className = LuaLib.lua_tostring (luaState, 1).ToString (); var translator = ObjectTranslatorPool.Instance.Find (luaState);
var klass = FindType (className); return translator.importTypeInternal (luaState);
}
if (!klass.IsNull ())
pushType (luaState, klass); private int importTypeInternal (LuaCore.lua_State luaState)
else {
LuaLib.lua_pushnil (luaState); string className = LuaLib.lua_tostring (luaState, 1).ToString ();
var klass = FindType (className);
return 1;
} if (!klass.IsNull ())
pushType (luaState, klass);
/* else
* Implementation of make_object. Registers a table (first LuaLib.lua_pushnil (luaState);
* argument in the stack) as an object subclassing the
* type passed as second argument in the stack. return 1;
*/ }
/*
* Implementation of make_object. Registers a table (first
* argument in the stack) as an object subclassing the
* type passed as second argument in the stack.
*/
#if MONOTOUCH #if MONOTOUCH
[MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_CFunction))] [MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_CFunction))]
#endif #endif
[System.Runtime.InteropServices.AllowReversePInvokeCalls] [System.Runtime.InteropServices.AllowReversePInvokeCalls]
private int registerTable (LuaCore.lua_State luaState) private static int registerTable (LuaCore.lua_State luaState)
{ {
if (LuaLib.lua_type (luaState, 1) == LuaTypes.Table) { var translator = ObjectTranslatorPool.Instance.Find (luaState);
var luaTable = getTable (luaState, 1); return translator.registerTableInternal (luaState);
string superclassName = LuaLib.lua_tostring (luaState, 2).ToString (); }
if (!superclassName.IsNull ()) { private int registerTableInternal (LuaCore.lua_State luaState)
var klass = FindType (superclassName); {
if (LuaLib.lua_type (luaState, 1) == LuaTypes.Table) {
if (!klass.IsNull ()) { var luaTable = getTable (luaState, 1);
// Creates and pushes the object in the stack, setting string superclassName = LuaLib.lua_tostring (luaState, 2).ToString ();
// it as the metatable of the first argument
object obj = CodeGeneration.Instance.GetClassInstance (klass, luaTable); if (!superclassName.IsNull ()) {
pushObject (luaState, obj, "luaNet_metatable"); var klass = FindType (superclassName);
LuaLib.lua_newtable (luaState);
LuaLib.lua_pushstring (luaState, "__index"); if (!klass.IsNull ()) {
LuaLib.lua_pushvalue (luaState, -3); // Creates and pushes the object in the stack, setting
LuaLib.lua_settable (luaState, -3); // it as the metatable of the first argument
LuaLib.lua_pushstring (luaState, "__newindex"); object obj = CodeGeneration.Instance.GetClassInstance (klass, luaTable);
LuaLib.lua_pushvalue (luaState, -3); pushObject (luaState, obj, "luaNet_metatable");
LuaLib.lua_settable (luaState, -3); LuaLib.lua_newtable (luaState);
LuaLib.lua_setmetatable (luaState, 1); LuaLib.lua_pushstring (luaState, "__index");
// Pushes the object again, this time as the base field LuaLib.lua_pushvalue (luaState, -3);
// of the table and with the luaNet_searchbase metatable LuaLib.lua_settable (luaState, -3);
LuaLib.lua_pushstring (luaState, "base"); LuaLib.lua_pushstring (luaState, "__newindex");
int index = addObject (obj); LuaLib.lua_pushvalue (luaState, -3);
pushNewObject (luaState, obj, index, "luaNet_searchbase"); LuaLib.lua_settable (luaState, -3);
LuaLib.lua_rawset (luaState, 1); LuaLib.lua_setmetatable (luaState, 1);
} else // Pushes the object again, this time as the base field
throwError (luaState, "register_table: can not find superclass '" + superclassName + "'"); // of the table and with the luaNet_searchbase metatable
} else LuaLib.lua_pushstring (luaState, "base");
throwError (luaState, "register_table: superclass name can not be null"); int index = addObject (obj);
} else pushNewObject (luaState, obj, index, "luaNet_searchbase");
throwError (luaState, "register_table: first arg is not a table"); LuaLib.lua_rawset (luaState, 1);
} else
return 0; throwError (luaState, "register_table: can not find superclass '" + superclassName + "'");
} } else
throwError (luaState, "register_table: superclass name can not be null");
/* } else
* Implementation of free_object. Clears the metatable and the throwError (luaState, "register_table: first arg is not a table");
* base field, freeing the created object for garbage-collection
*/ return 0;
}
/*
* Implementation of free_object. Clears the metatable and the
* base field, freeing the created object for garbage-collection
*/
#if MONOTOUCH #if MONOTOUCH
[MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_CFunction))] [MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_CFunction))]
#endif #endif
[System.Runtime.InteropServices.AllowReversePInvokeCalls] [System.Runtime.InteropServices.AllowReversePInvokeCalls]
private int unregisterTable (LuaCore.lua_State luaState) private static int unregisterTable (LuaCore.lua_State luaState)
{ {
try { var translator = ObjectTranslatorPool.Instance.Find (luaState);
if (LuaLib.lua_getmetatable (luaState, 1) != 0) { return translator.unregisterTableInternal (luaState);
LuaLib.lua_pushstring (luaState, "__index"); }
LuaLib.lua_gettable (luaState, -2);
object obj = getRawNetObject (luaState, -1); private int unregisterTableInternal (LuaCore.lua_State luaState)
{
if (obj.IsNull ()) try {
throwError (luaState, "unregister_table: arg is not valid table"); if (LuaLib.lua_getmetatable (luaState, 1) != 0) {
LuaLib.lua_pushstring (luaState, "__index");
var luaTableField = obj.GetType ().GetField ("__luaInterface_luaTable"); LuaLib.lua_gettable (luaState, -2);
object obj = getRawNetObject (luaState, -1);
if (luaTableField.IsNull ())
throwError (luaState, "unregister_table: arg is not valid table"); if (obj.IsNull ())
throwError (luaState, "unregister_table: arg is not valid table");
luaTableField.SetValue (obj, null);
LuaLib.lua_pushnil (luaState); var luaTableField = obj.GetType ().GetField ("__luaInterface_luaTable");
LuaLib.lua_setmetatable (luaState, 1);
LuaLib.lua_pushstring (luaState, "base"); if (luaTableField.IsNull ())
LuaLib.lua_pushnil (luaState); throwError (luaState, "unregister_table: arg is not valid table");
LuaLib.lua_settable (luaState, 1);
} else luaTableField.SetValue (obj, null);
throwError (luaState, "unregister_table: arg is not valid table"); LuaLib.lua_pushnil (luaState);
} catch (Exception e) { LuaLib.lua_setmetatable (luaState, 1);
throwError (luaState, e.Message); LuaLib.lua_pushstring (luaState, "base");
} LuaLib.lua_pushnil (luaState);
LuaLib.lua_settable (luaState, 1);
return 0; } else
} throwError (luaState, "unregister_table: arg is not valid table");
} catch (Exception e) {
/* throwError (luaState, e.Message);
* Implementation of get_method_bysig. Returns nil }
* if no matching method is not found.
*/ return 0;
}
/*
* Implementation of get_method_bysig. Returns nil
* if no matching method is not found.
*/
#if MONOTOUCH #if MONOTOUCH
[MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_CFunction))] [MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_CFunction))]
#endif #endif
[System.Runtime.InteropServices.AllowReversePInvokeCalls] [System.Runtime.InteropServices.AllowReversePInvokeCalls]
private int getMethodSignature (LuaCore.lua_State luaState) private static int getMethodSignature (LuaCore.lua_State luaState)
{ {
IReflect klass; var translator = ObjectTranslatorPool.Instance.Find (luaState);
object target; return translator.getMethodSignatureInternal (luaState);
int udata = LuaLib.luanet_checkudata (luaState, 1, "luaNet_class"); }
if (udata != -1) { private int getMethodSignatureInternal (LuaCore.lua_State luaState)
klass = (IReflect)objects [udata]; {
target = null; IReflect klass;
} else { object target;
target = getRawNetObject (luaState, 1); int udata = LuaLib.luanet_checkudata (luaState, 1, "luaNet_class");
if (target.IsNull ()) { if (udata != -1) {
throwError (luaState, "get_method_bysig: first arg is not type or object reference"); klass = (IReflect)objects [udata];
LuaLib.lua_pushnil (luaState); target = null;
return 1; } else {
} target = getRawNetObject (luaState, 1);
klass = target.GetType (); if (target.IsNull ()) {
} throwError (luaState, "get_method_bysig: first arg is not type or object reference");
LuaLib.lua_pushnil (luaState);
string methodName = LuaLib.lua_tostring (luaState, 2).ToString (); return 1;
var signature = new Type[LuaLib.lua_gettop (luaState) - 2]; }
for (int i = 0; i < signature.Length; i++) klass = target.GetType ();
signature [i] = FindType (LuaLib.lua_tostring (luaState, i + 3).ToString ()); }
try { string methodName = LuaLib.lua_tostring (luaState, 2).ToString ();
//CP: Added ignore case var signature = new Type[LuaLib.lua_gettop (luaState) - 2];
var method = klass.GetMethod (methodName, BindingFlags.Public | BindingFlags.Static |
BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.IgnoreCase, null, signature, null); for (int i = 0; i < signature.Length; i++)
pushFunction (luaState, new LuaCore.lua_CFunction ((new LuaMethodWrapper (this, target, klass, method)).invokeFunction)); signature [i] = FindType (LuaLib.lua_tostring (luaState, i + 3).ToString ());
} catch (Exception e) {
throwError (luaState, e); try {
LuaLib.lua_pushnil (luaState); //CP: Added ignore case
} var method = klass.GetMethod (methodName, BindingFlags.Public | BindingFlags.Static |
BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.IgnoreCase, null, signature, null);
return 1; pushFunction (luaState, new LuaCore.lua_CFunction ((new LuaMethodWrapper (this, target, klass, method)).invokeFunction));
} } catch (Exception e) {
throwError (luaState, e);
/* LuaLib.lua_pushnil (luaState);
* Implementation of get_constructor_bysig. Returns nil }
* if no matching constructor is found.
*/ return 1;
}
/*
* Implementation of get_constructor_bysig. Returns nil
* if no matching constructor is found.
*/
#if MONOTOUCH #if MONOTOUCH
[MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_CFunction))] [MonoTouch.MonoPInvokeCallback (typeof (LuaCore.lua_CFunction))]
#endif #endif
[System.Runtime.InteropServices.AllowReversePInvokeCalls] [System.Runtime.InteropServices.AllowReversePInvokeCalls]
private int getConstructorSignature (LuaCore.lua_State luaState) private static int getConstructorSignature (LuaCore.lua_State luaState)
{ {
IReflect klass = null; var translator = ObjectTranslatorPool.Instance.Find (luaState);
int udata = LuaLib.luanet_checkudata (luaState, 1, "luaNet_class"); return translator.getConstructorSignatureInternal (luaState);
}
if (udata != -1)
klass = (IReflect)objects [udata]; private int getConstructorSignatureInternal (LuaCore.lua_State luaState)
{
if (klass.IsNull ()) IReflect klass = null;
throwError (luaState, "get_constructor_bysig: first arg is invalid type reference"); int udata = LuaLib.luanet_checkudata (luaState, 1, "luaNet_class");
var signature = new Type[LuaLib.lua_gettop (luaState) - 1]; if (udata != -1)
klass = (IReflect)objects [udata];
for (int i = 0; i < signature.Length; i++)
signature [i] = FindType (LuaLib.lua_tostring (luaState, i + 2).ToString ()); if (klass.IsNull ())
throwError (luaState, "get_constructor_bysig: first arg is invalid type reference");
try {
ConstructorInfo constructor = klass.UnderlyingSystemType.GetConstructor (signature); var signature = new Type[LuaLib.lua_gettop (luaState) - 1];
pushFunction (luaState, new LuaCore.lua_CFunction ((new LuaMethodWrapper (this, null, klass, constructor)).invokeFunction));
} catch (Exception e) { for (int i = 0; i < signature.Length; i++)
throwError (luaState, e); signature [i] = FindType (LuaLib.lua_tostring (luaState, i + 2).ToString ());
LuaLib.lua_pushnil (luaState);
} try {
ConstructorInfo constructor = klass.UnderlyingSystemType.GetConstructor (signature);
return 1; pushFunction (luaState, new LuaCore.lua_CFunction ((new LuaMethodWrapper (this, null, klass, constructor)).invokeFunction));
} } catch (Exception e) {
throwError (luaState, e);
/* LuaLib.lua_pushnil (luaState);
* Pushes a type reference into the stack }
*/
internal void pushType (LuaCore.lua_State luaState, Type t) return 1;
{ }
pushObject (luaState, new ProxyType (t), "luaNet_class");
} /*
* Pushes a type reference into the stack
/* */
* Pushes a delegate into the stack internal void pushType (LuaCore.lua_State luaState, Type t)
*/ {
internal void pushFunction (LuaCore.lua_State luaState, LuaCore.lua_CFunction func) pushObject (luaState, new ProxyType (t), "luaNet_class");
{ }
pushObject (luaState, func, "luaNet_function");
} /*
* Pushes a delegate into the stack
/* */
* Pushes a CLR object into the Lua stack as an userdata internal void pushFunction (LuaCore.lua_State luaState, LuaCore.lua_CFunction func)
* with the provided metatable {
*/ pushObject (luaState, func, "luaNet_function");
internal void pushObject (LuaCore.lua_State luaState, object o, string metatable) }
{
int index = -1; /*
* Pushes a CLR object into the Lua stack as an userdata
// Pushes nil * with the provided metatable
if (o.IsNull ()) { */
LuaLib.lua_pushnil (luaState); internal void pushObject (LuaCore.lua_State luaState, object o, string metatable)
return; {
} int index = -1;
// Object already in the list of Lua objects? Push the stored reference. // Pushes nil
bool found = objectsBackMap.TryGetValue (o, out index); if (o.IsNull ()) {
LuaLib.lua_pushnil (luaState);
if (found) { return;
LuaLib.luaL_getmetatable (luaState, "luaNet_objects"); }
LuaLib.lua_rawgeti (luaState, -1, index);
// Object already in the list of Lua objects? Push the stored reference.
// Note: starting with lua5.1 the garbage collector may remove weak reference items (such as our luaNet_objects values) when the initial GC sweep bool found = objectsBackMap.TryGetValue (o, out index);
// occurs, but the actual call of the __gc finalizer for that object may not happen until a little while later. During that window we might call
// this routine and find the element missing from luaNet_objects, but collectObject() has not yet been called. In that case, we go ahead and call collect if (found) {
// object here LuaLib.luaL_getmetatable (luaState, "luaNet_objects");
// did we find a non nil object in our table? if not, we need to call collect object LuaLib.lua_rawgeti (luaState, -1, index);
var type = LuaLib.lua_type (luaState, -1);
if (type != LuaTypes.Nil) { // Note: starting with lua5.1 the garbage collector may remove weak reference items (such as our luaNet_objects values) when the initial GC sweep
LuaLib.lua_remove (luaState, -2); // drop the metatable - we're going to leave our object on the stack // occurs, but the actual call of the __gc finalizer for that object may not happen until a little while later. During that window we might call
return; // this routine and find the element missing from luaNet_objects, but collectObject() has not yet been called. In that case, we go ahead and call collect
} // object here
// did we find a non nil object in our table? if not, we need to call collect object
// MetaFunctions.dumpStack(this, luaState); var type = LuaLib.lua_type (luaState, -1);
LuaLib.lua_remove (luaState, -1); // remove the nil object value if (type != LuaTypes.Nil) {
LuaLib.lua_remove (luaState, -1); // remove the metatable LuaLib.lua_remove (luaState, -2); // drop the metatable - we're going to leave our object on the stack
collectObject (o, index); // Remove from both our tables and fall out to get a new ID return;
} }
index = addObject (o); // MetaFunctions.dumpStack(this, luaState);
pushNewObject (luaState, o, index, metatable); LuaLib.lua_remove (luaState, -1); // remove the nil object value
} LuaLib.lua_remove (luaState, -1); // remove the metatable
collectObject (o, index); // Remove from both our tables and fall out to get a new ID
/* }
* Pushes a new object into the Lua stack with the provided
* metatable index = addObject (o);
*/ pushNewObject (luaState, o, index, metatable);
private void pushNewObject (LuaCore.lua_State luaState, object o, int index, string metatable) }
{
if (metatable == "luaNet_metatable") { /*
// Gets or creates the metatable for the object's type * Pushes a new object into the Lua stack with the provided
LuaLib.luaL_getmetatable (luaState, o.GetType ().AssemblyQualifiedName); * metatable
*/
if (LuaLib.lua_isnil (luaState, -1)) { private void pushNewObject (LuaCore.lua_State luaState, object o, int index, string metatable)
LuaLib.lua_settop (luaState, -2); {
LuaLib.luaL_newmetatable (luaState, o.GetType ().AssemblyQualifiedName); if (metatable == "luaNet_metatable") {
LuaLib.lua_pushstring (luaState, "cache"); // Gets or creates the metatable for the object's type
LuaLib.lua_newtable (luaState); LuaLib.luaL_getmetatable (luaState, o.GetType ().AssemblyQualifiedName);
LuaLib.lua_rawset (luaState, -3);
LuaLib.lua_pushlightuserdata (luaState, LuaLib.luanet_gettag ()); if (LuaLib.lua_isnil (luaState, -1)) {
LuaLib.lua_pushnumber (luaState, 1); LuaLib.lua_settop (luaState, -2);
LuaLib.lua_rawset (luaState, -3); LuaLib.luaL_newmetatable (luaState, o.GetType ().AssemblyQualifiedName);
LuaLib.lua_pushstring (luaState, "__index"); LuaLib.lua_pushstring (luaState, "cache");
LuaLib.lua_pushstring (luaState, "luaNet_indexfunction"); LuaLib.lua_newtable (luaState);
LuaLib.lua_rawget (luaState, (int)LuaIndexes.Registry); LuaLib.lua_rawset (luaState, -3);
LuaLib.lua_rawset (luaState, -3); LuaLib.lua_pushlightuserdata (luaState, LuaLib.luanet_gettag ());
LuaLib.lua_pushstring (luaState, "__gc"); LuaLib.lua_pushnumber (luaState, 1);
LuaLib.lua_pushstdcallcfunction (luaState, metaFunctions.gcFunction); LuaLib.lua_rawset (luaState, -3);
LuaLib.lua_rawset (luaState, -3); LuaLib.lua_pushstring (luaState, "__index");
LuaLib.lua_pushstring (luaState, "__tostring"); LuaLib.lua_pushstring (luaState, "luaNet_indexfunction");
LuaLib.lua_pushstdcallcfunction (luaState, metaFunctions.toStringFunction); LuaLib.lua_rawget (luaState, (int)LuaIndexes.Registry);
LuaLib.lua_rawset (luaState, -3); LuaLib.lua_rawset (luaState, -3);
LuaLib.lua_pushstring (luaState, "__newindex"); LuaLib.lua_pushstring (luaState, "__gc");
LuaLib.lua_pushstdcallcfunction (luaState, metaFunctions.newindexFunction); LuaLib.lua_pushstdcallcfunction (luaState, metaFunctions.gcFunction);
LuaLib.lua_rawset (luaState, -3); LuaLib.lua_rawset (luaState, -3);
} LuaLib.lua_pushstring (luaState, "__tostring");
} else LuaLib.lua_pushstdcallcfunction (luaState, metaFunctions.toStringFunction);
LuaLib.luaL_getmetatable (luaState, metatable); LuaLib.lua_rawset (luaState, -3);
LuaLib.lua_pushstring (luaState, "__newindex");
// Stores the object index in the Lua list and pushes the LuaLib.lua_pushstdcallcfunction (luaState, metaFunctions.newindexFunction);
// index into the Lua stack LuaLib.lua_rawset (luaState, -3);
LuaLib.luaL_getmetatable (luaState, "luaNet_objects"); }
LuaLib.luanet_newudata (luaState, index); } else
LuaLib.lua_pushvalue (luaState, -3); LuaLib.luaL_getmetatable (luaState, metatable);
LuaLib.lua_remove (luaState, -4);
LuaLib.lua_setmetatable (luaState, -2); // Stores the object index in the Lua list and pushes the
LuaLib.lua_pushvalue (luaState, -1); // index into the Lua stack
LuaLib.lua_rawseti (luaState, -3, index); LuaLib.luaL_getmetatable (luaState, "luaNet_objects");
LuaLib.lua_remove (luaState, -2); LuaLib.luanet_newudata (luaState, index);
} LuaLib.lua_pushvalue (luaState, -3);
LuaLib.lua_remove (luaState, -4);
/* LuaLib.lua_setmetatable (luaState, -2);
* Gets an object from the Lua stack with the desired type, if it matches, otherwise LuaLib.lua_pushvalue (luaState, -1);
* returns null. LuaLib.lua_rawseti (luaState, -3, index);
*/ LuaLib.lua_remove (luaState, -2);
internal object getAsType (LuaCore.lua_State luaState, int stackPos, Type paramType) }
{
var extractor = typeChecker.checkType (luaState, stackPos, paramType); /*
return !extractor.IsNull () ? extractor (luaState, stackPos) : null; * Gets an object from the Lua stack with the desired type, if it matches, otherwise
} * returns null.
*/
/// <summary> internal object getAsType (LuaCore.lua_State luaState, int stackPos, Type paramType)
/// Given the Lua int ID for an object remove it from our maps {
/// </summary> var extractor = typeChecker.checkType (luaState, stackPos, paramType);
/// <param name = "udata"></param> return !extractor.IsNull () ? extractor (luaState, stackPos) : null;
internal void collectObject (int udata) }
{
object o; /// <summary>
bool found = objects.TryGetValue (udata, out o); /// Given the Lua int ID for an object remove it from our maps
/// </summary>
// The other variant of collectObject might have gotten here first, in that case we will silently ignore the missing entry /// <param name = "udata"></param>
if (found) { internal void collectObject (int udata)
// Debug.WriteLine("Removing " + o.ToString() + " @ " + udata); {
objects.Remove (udata); object o;
objectsBackMap.Remove (o); bool found = objects.TryGetValue (udata, out o);
}
} // The other variant of collectObject might have gotten here first, in that case we will silently ignore the missing entry
if (found) {
/// <summary> // Debug.WriteLine("Removing " + o.ToString() + " @ " + udata);
/// Given an object reference, remove it from our maps objects.Remove (udata);
/// </summary> objectsBackMap.Remove (o);
/// <param name = "udata"></param> }
private void collectObject (object o, int udata) }
{
// Debug.WriteLine("Removing " + o.ToString() + " @ " + udata); /// <summary>
objects.Remove (udata); /// Given an object reference, remove it from our maps
objectsBackMap.Remove (o); /// </summary>
} /// <param name = "udata"></param>
private void collectObject (object o, int udata)
private int addObject (object obj) {
{ // Debug.WriteLine("Removing " + o.ToString() + " @ " + udata);
// New object: inserts it in the list objects.Remove (udata);
int index = nextObj++; objectsBackMap.Remove (o);
// Debug.WriteLine("Adding " + obj.ToString() + " @ " + index); }
objects [index] = obj;
objectsBackMap [obj] = index; private int addObject (object obj)
return index; {
} // New object: inserts it in the list
int index = nextObj++;
/* // Debug.WriteLine("Adding " + obj.ToString() + " @ " + index);
* Gets an object from the Lua stack according to its Lua type. objects [index] = obj;
*/ objectsBackMap [obj] = index;
internal object getObject (LuaCore.lua_State luaState, int index) return index;
{ }
var type = LuaLib.lua_type (luaState, index);
/*
switch (type) { * Gets an object from the Lua stack according to its Lua type.
case LuaTypes.Number: */
{ internal object getObject (LuaCore.lua_State luaState, int index)
return LuaLib.lua_tonumber (luaState, index); {
} var type = LuaLib.lua_type (luaState, index);
case LuaTypes.String:
{ switch (type) {
return LuaLib.lua_tostring (luaState, index); case LuaTypes.Number:
} {
case LuaTypes.Boolean: return LuaLib.lua_tonumber (luaState, index);
{ }
return LuaLib.lua_toboolean (luaState, index); case LuaTypes.String:
} {
case LuaTypes.Table: return LuaLib.lua_tostring (luaState, index);
{ }
return getTable (luaState, index); case LuaTypes.Boolean:
} {
case LuaTypes.Function: return LuaLib.lua_toboolean (luaState, index);
{ }
return getFunction (luaState, index); case LuaTypes.Table:
} {
case LuaTypes.UserData: return getTable (luaState, index);
{ }
int udata = LuaLib.luanet_tonetobject (luaState, index); case LuaTypes.Function:
return udata != -1 ? objects [udata] : getUserData (luaState, index); {
} return getFunction (luaState, index);
default: }
return null; case LuaTypes.UserData:
} {
} int udata = LuaLib.luanet_tonetobject (luaState, index);
return udata != -1 ? objects [udata] : getUserData (luaState, index);
/* }
* Gets the table in the index positon of the Lua stack. default:
*/ return null;
internal LuaTable getTable (LuaCore.lua_State luaState, int index) }
{ }
LuaLib.lua_pushvalue (luaState, index);
return new LuaTable (LuaLib.lua_ref (luaState, 1), interpreter); /*
} * Gets the table in the index positon of the Lua stack.
*/
/* internal LuaTable getTable (LuaCore.lua_State luaState, int index)
* Gets the userdata in the index positon of the Lua stack. {
*/ LuaLib.lua_pushvalue (luaState, index);
internal LuaUserData getUserData (LuaCore.lua_State luaState, int index) return new LuaTable (LuaLib.lua_ref (luaState, 1), interpreter);
{ }
LuaLib.lua_pushvalue (luaState, index);
return new LuaUserData (LuaLib.lua_ref (luaState, 1), interpreter); /*
} * Gets the userdata in the index positon of the Lua stack.
*/
/* internal LuaUserData getUserData (LuaCore.lua_State luaState, int index)
* Gets the function in the index positon of the Lua stack. {
*/ LuaLib.lua_pushvalue (luaState, index);
internal LuaFunction getFunction (LuaCore.lua_State luaState, int index) return new LuaUserData (LuaLib.lua_ref (luaState, 1), interpreter);
{ }
LuaLib.lua_pushvalue (luaState, index);
return new LuaFunction (LuaLib.lua_ref (luaState, 1), interpreter); /*
} * Gets the function in the index positon of the Lua stack.
*/
/* internal LuaFunction getFunction (LuaCore.lua_State luaState, int index)
* Gets the CLR object in the index positon of the Lua stack. Returns {
* delegates as Lua functions. LuaLib.lua_pushvalue (luaState, index);
*/ return new LuaFunction (LuaLib.lua_ref (luaState, 1), interpreter);
internal object getNetObject (LuaCore.lua_State luaState, int index) }
{
int idx = LuaLib.luanet_tonetobject (luaState, index); /*
return idx != -1 ? objects [idx] : null; * Gets the CLR object in the index positon of the Lua stack. Returns
} * delegates as Lua functions.
*/
/* internal object getNetObject (LuaCore.lua_State luaState, int index)
* Gets the CLR object in the index positon of the Lua stack. Returns {
* delegates as is. int idx = LuaLib.luanet_tonetobject (luaState, index);
*/ return idx != -1 ? objects [idx] : null;
internal object getRawNetObject (LuaCore.lua_State luaState, int index) }
{
int udata = LuaLib.luanet_rawnetobj (luaState, index); /*
return udata != -1 ? objects [udata] : null; * Gets the CLR object in the index positon of the Lua stack. Returns
} * delegates as is.
*/
/* internal object getRawNetObject (LuaCore.lua_State luaState, int index)
* Pushes the entire array into the Lua stack and returns the number {
* of elements pushed. int udata = LuaLib.luanet_rawnetobj (luaState, index);
*/ return udata != -1 ? objects [udata] : null;
internal int returnValues (LuaCore.lua_State luaState, object[] returnValues) }
{
if (LuaLib.lua_checkstack (luaState, returnValues.Length + 5)) { /*
for (int i = 0; i < returnValues.Length; i++) * Pushes the entire array into the Lua stack and returns the number
push (luaState, returnValues [i]); * of elements pushed.
*/
return returnValues.Length; internal int returnValues (LuaCore.lua_State luaState, object[] returnValues)
} else {
return 0; if (LuaLib.lua_checkstack (luaState, returnValues.Length + 5)) {
} for (int i = 0; i < returnValues.Length; i++)
push (luaState, returnValues [i]);
/*
* Gets the values from the provided index to return returnValues.Length;
* the top of the stack and returns them in an array. } else
*/ return 0;
internal object[] popValues (LuaCore.lua_State luaState, int oldTop) }
{
int newTop = LuaLib.lua_gettop (luaState); /*
* Gets the values from the provided index to
if (oldTop == newTop) * the top of the stack and returns them in an array.
return null; */
else { internal object[] popValues (LuaCore.lua_State luaState, int oldTop)
var returnValues = new ArrayList (); {
for (int i = oldTop+1; i <= newTop; i++) int newTop = LuaLib.lua_gettop (luaState);
returnValues.Add (getObject (luaState, i));
if (oldTop == newTop)
LuaLib.lua_settop (luaState, oldTop); return null;
return returnValues.ToArray (); else {
} var returnValues = new ArrayList ();
} for (int i = oldTop+1; i <= newTop; i++)
returnValues.Add (getObject (luaState, i));
/*
* Gets the values from the provided index to LuaLib.lua_settop (luaState, oldTop);
* the top of the stack and returns them in an array, casting return returnValues.ToArray ();
* them to the provided types. }
*/ }
internal object[] popValues (LuaCore.lua_State luaState, int oldTop, Type[] popTypes)
{ /*
int newTop = LuaLib.lua_gettop (luaState); * Gets the values from the provided index to
* the top of the stack and returns them in an array, casting
if (oldTop == newTop) * them to the provided types.
return null; */
else { internal object[] popValues (LuaCore.lua_State luaState, int oldTop, Type[] popTypes)
int iTypes; {
var returnValues = new ArrayList (); int newTop = LuaLib.lua_gettop (luaState);
if (popTypes [0] == typeof(void)) if (oldTop == newTop)
iTypes = 1; return null;
else else {
iTypes = 0; int iTypes;
var returnValues = new ArrayList ();
for (int i = oldTop+1; i <= newTop; i++) {
returnValues.Add (getAsType (luaState, i, popTypes [iTypes])); if (popTypes [0] == typeof(void))
iTypes++; iTypes = 1;
} else
iTypes = 0;
LuaLib.lua_settop (luaState, oldTop);
return returnValues.ToArray (); for (int i = oldTop+1; i <= newTop; i++) {
} returnValues.Add (getAsType (luaState, i, popTypes [iTypes]));
} iTypes++;
}
// kevinh - the following line doesn't work for remoting proxies - they always return a match for 'is'
// else if(o is ILuaGeneratedType) LuaLib.lua_settop (luaState, oldTop);
private static bool IsILua (object o) return returnValues.ToArray ();
{ }
if (o is ILuaGeneratedType) { }
// Make sure we are _really_ ILuaGenerated
var typ = o.GetType (); // kevinh - the following line doesn't work for remoting proxies - they always return a match for 'is'
return (!typ.GetInterface ("ILuaGeneratedType").IsNull ()); // else if(o is ILuaGeneratedType)
} else private static bool IsILua (object o)
return false; {
} if (o is ILuaGeneratedType) {
// Make sure we are _really_ ILuaGenerated
/* var typ = o.GetType ();
* Pushes the object into the Lua stack according to its type. return (!typ.GetInterface ("ILuaGeneratedType").IsNull ());
*/ } else
internal void push (LuaCore.lua_State luaState, object o) return false;
{ }
if (o.IsNull ())
LuaLib.lua_pushnil (luaState); /*
else if (o is sbyte || o is byte || o is short || o is ushort || * Pushes the object into the Lua stack according to its type.
o is int || o is uint || o is long || o is float || */
o is ulong || o is decimal || o is double) { internal void push (LuaCore.lua_State luaState, object o)
double d = Convert.ToDouble (o); {
LuaLib.lua_pushnumber (luaState, d); if (o.IsNull ())
} else if (o is char) { LuaLib.lua_pushnil (luaState);
double d = (char)o; else if (o is sbyte || o is byte || o is short || o is ushort ||
LuaLib.lua_pushnumber (luaState, d); o is int || o is uint || o is long || o is float ||
} else if (o is string) { o is ulong || o is decimal || o is double) {
string str = (string)o; double d = Convert.ToDouble (o);
LuaLib.lua_pushstring (luaState, str); LuaLib.lua_pushnumber (luaState, d);
} else if (o is bool) { } else if (o is char) {
bool b = (bool)o; double d = (char)o;
LuaLib.lua_pushboolean (luaState, b); LuaLib.lua_pushnumber (luaState, d);
} else if (IsILua (o)) } else if (o is string) {
(((ILuaGeneratedType)o).__luaInterface_getLuaTable ()).push (luaState); string str = (string)o;
else if (o is LuaTable) LuaLib.lua_pushstring (luaState, str);
((LuaTable)o).push (luaState); } else if (o is bool) {
else if (o is LuaCore.lua_CFunction) bool b = (bool)o;
pushFunction (luaState, (LuaCore.lua_CFunction)o); LuaLib.lua_pushboolean (luaState, b);
else if (o is LuaFunction) } else if (IsILua (o))
((LuaFunction)o).push (luaState); (((ILuaGeneratedType)o).__luaInterface_getLuaTable ()).push (luaState);
else else if (o is LuaTable)
pushObject (luaState, o, "luaNet_metatable"); ((LuaTable)o).push (luaState);
} else if (o is LuaCore.lua_CFunction)
pushFunction (luaState, (LuaCore.lua_CFunction)o);
/* else if (o is LuaFunction)
* Checks if the method matches the arguments in the Lua stack, getting ((LuaFunction)o).push (luaState);
* the arguments if it does. else
*/ pushObject (luaState, o, "luaNet_metatable");
internal bool matchParameters (LuaCore.lua_State luaState, MethodBase method, ref MethodCache methodCache) }
{
return metaFunctions.matchParameters (luaState, method, ref methodCache); /*
} * Checks if the method matches the arguments in the Lua stack, getting
} * the arguments if it does.
*/
internal bool matchParameters (LuaCore.lua_State luaState, MethodBase method, ref MethodCache methodCache)
{
return metaFunctions.matchParameters (luaState, method, ref methodCache);
}
}
} }
\ No newline at end of file
using System;
using System.Collections.Generic;
namespace LuaInterface
{
#if USE_KOPILUA
using LuaCore = KopiLua.Lua;
#else
using LuaCore = KeraLua.Lua;
#endif
internal class ObjectTranslatorPool
{
private static volatile ObjectTranslatorPool instance = new ObjectTranslatorPool ();
private static object syncRoot = new object ();
private Dictionary<LuaCore.lua_State, ObjectTranslator> translators = new Dictionary<LuaCore.lua_State, ObjectTranslator>();
public static ObjectTranslatorPool Instance
{
get
{
return instance;
}
}
public ObjectTranslatorPool ()
{
syncRoot = new Dictionary<LuaCore.lua_State, ObjectTranslator> ();
}
public void Add (LuaCore.lua_State luaState, ObjectTranslator translator)
{
translators.Add(luaState , translator);
}
public ObjectTranslator Find (LuaCore.lua_State luaState)
{
if (!translators.ContainsKey(luaState))
return null;
return translators [luaState];
}
public void Remove (LuaCore.lua_State luaState)
{
if (!translators.ContainsKey (luaState))
return;
translators.Remove (luaState);
}
}
}
...@@ -64,7 +64,9 @@ ...@@ -64,7 +64,9 @@
<IpaPackageName /> <IpaPackageName />
<MtouchI18n /> <MtouchI18n />
<MtouchArch>ARMv7</MtouchArch> <MtouchArch>ARMv7</MtouchArch>
<MtouchLink>Full</MtouchLink> <MtouchLink>None</MtouchLink>
<MtouchUseLlvm>true</MtouchUseLlvm>
<MtouchUseThumb>true</MtouchUseThumb>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Ad-Hoc|iPhone' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Ad-Hoc|iPhone' ">
<DebugType>none</DebugType> <DebugType>none</DebugType>
......
...@@ -348,6 +348,16 @@ namespace LuaInterfaceTest ...@@ -348,6 +348,16 @@ namespace LuaInterfaceTest
//lua.RegisterFunction("regularMethod", genericClass, typeof(TestClassGeneric<>).GetMethod("RegularMethod")); //lua.RegisterFunction("regularMethod", genericClass, typeof(TestClassGeneric<>).GetMethod("RegularMethod"));
using (Lua lua = new Lua ()) { using (Lua lua = new Lua ()) {
TestClassWithGenericMethod classWithGenericMethod = new TestClassWithGenericMethod (); TestClassWithGenericMethod classWithGenericMethod = new TestClassWithGenericMethod ();
////////////////////////////////////////////////////////////////////////////
/// ////////////////////////////////////////////////////////////////////////
/// IMPORTANT: Use generic method with the type you will call or generic methods will fail with iOS
/// ////////////////////////////////////////////////////////////////////////
classWithGenericMethod.GenericMethod<double>(99.0);
classWithGenericMethod.GenericMethod<TestClass>(new TestClass (99));
////////////////////////////////////////////////////////////////////////////
/// ////////////////////////////////////////////////////////////////////////
lua.RegisterFunction ("genericMethod2", classWithGenericMethod, typeof(TestClassWithGenericMethod).GetMethod ("GenericMethod")); lua.RegisterFunction ("genericMethod2", classWithGenericMethod, typeof(TestClassWithGenericMethod).GetMethod ("GenericMethod"));
try { try {
......
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