Unverified Commit 1cc74393 authored by Vinicius Jarina's avatar Vinicius Jarina Committed by GitHub
Browse files

* Giant cleanup/reshuffle of all files. (#265)

* * Giant cleanup/reshuffle of all files.

* * Update upstream `KeraLua` to `0.1.14`

* Fixed .NET Core build.

* Add runsettings file

* * Fixed nuspec `dependencies` node

* Ignore _ in branch names for package names.

* * Fixed nuspec.
parent 3f254585
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle ("ConsoleTest")]
[assembly: AssemblyDescription ("")]
[assembly: AssemblyConfiguration ("")]
[assembly: AssemblyCompany ("")]
[assembly: AssemblyProduct ("ConsoleTest")]
[assembly: AssemblyCopyright ("Copyright © 2015")]
[assembly: AssemblyTrademark ("")]
[assembly: AssemblyCulture ("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible (false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid ("7c99edf7-f9ea-40fd-9ff9-c463f501e21a")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion ("1.0.0.0")]
[assembly: AssemblyFileVersion ("1.0.0.0")]
#!/bin/sh
exec mono "@expanded_libdir@/@PACKAGE@/ConsoleTest.exe" "$@"
Subproject commit e5ef8341688d8a25e8cf6f6d812ab3da365399b6
Subproject commit 6855aea035e73911cb01da1f1616f2f579251e65
EXTRA_DIST =
#Warning: This is an automatically generated file, do not edit!
if ENABLE_DEBUG
SUBDIRS = KopiLua/KopiLua KeraLua/src NLua
endif
if ENABLE_DEBUGKOPILUA
SUBDIRS = KopiLua/KopiLua KeraLua/src NLua
endif
if ENABLE_RELEASE
SUBDIRS = KopiLua/KopiLua KeraLua/src NLua
endif
if ENABLE_RELEASEKOPILUA
SUBDIRS = KopiLua/KopiLua KeraLua/src NLua
endif
if ENABLE_DEBUG_X64
SUBDIRS = KopiLua/KopiLua KeraLua/src NLua
endif
if ENABLE_RELEASE_X64
SUBDIRS = KopiLua/KopiLua KeraLua/src NLua
endif
if ENABLE_DEBUGKOPILUA_X64
SUBDIRS = KopiLua/KopiLua KeraLua/src NLua
endif
if ENABLE_RELEASEKOPILUA_X64
SUBDIRS = KopiLua/KopiLua KeraLua/src NLua
endif
/*
* This file is part of NLua.
*
* Copyright (c) 2015 Vinicius Jarina (viniciusjarina@gmail.com)
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* 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
* THE SOFTWARE.
*/
using System;
using System.Reflection;
using System.Collections.Generic;
using NLua.Method;
using NLua.Extensions;
namespace NLua
{
#if USE_KOPILUA
using LuaCore = KopiLua.Lua;
using LuaState = KopiLua.LuaState;
#else
using LuaCore = KeraLua.Lua;
using LuaState = KeraLua.LuaState;
#endif
/*
* Type checking and conversion functions.
*
* Author: Fabio Mascarenhas
* Version: 1.0
*/
sealed class CheckType
{
Dictionary<Type, ExtractValue> extractValues = new Dictionary<Type, ExtractValue>();
ExtractValue extractNetObject;
ObjectTranslator translator;
public CheckType (ObjectTranslator translator)
{
this.translator = translator;
extractValues.Add(GetExtractDictionaryKey(typeof(object)), new ExtractValue(GetAsObject));
extractValues.Add(GetExtractDictionaryKey(typeof(sbyte)), new ExtractValue(GetAsSbyte));
extractValues.Add(GetExtractDictionaryKey(typeof(byte)), new ExtractValue(GetAsByte));
extractValues.Add(GetExtractDictionaryKey(typeof(short)), new ExtractValue(GetAsShort));
extractValues.Add(GetExtractDictionaryKey(typeof(ushort)), new ExtractValue(GetAsUshort));
extractValues.Add(GetExtractDictionaryKey(typeof(int)), new ExtractValue(GetAsInt));
extractValues.Add(GetExtractDictionaryKey(typeof(uint)), new ExtractValue(GetAsUint));
extractValues.Add(GetExtractDictionaryKey(typeof(long)), new ExtractValue(GetAsLong));
extractValues.Add(GetExtractDictionaryKey(typeof(ulong)), new ExtractValue(GetAsUlong));
extractValues.Add(GetExtractDictionaryKey(typeof(double)), new ExtractValue(GetAsDouble));
extractValues.Add(GetExtractDictionaryKey(typeof(char)), new ExtractValue(GetAsChar));
extractValues.Add(GetExtractDictionaryKey(typeof(float)), new ExtractValue(GetAsFloat));
extractValues.Add(GetExtractDictionaryKey(typeof(decimal)), new ExtractValue(GetAsDecimal));
extractValues.Add(GetExtractDictionaryKey(typeof(bool)), new ExtractValue(GetAsBoolean));
extractValues.Add(GetExtractDictionaryKey(typeof(string)), new ExtractValue(GetAsString));
extractValues.Add(GetExtractDictionaryKey(typeof(char[])), new ExtractValue (GetAsCharArray));
extractValues.Add(GetExtractDictionaryKey(typeof(LuaFunction)), new ExtractValue(GetAsFunction));
extractValues.Add(GetExtractDictionaryKey(typeof(LuaTable)), new ExtractValue(GetAsTable));
extractValues.Add(GetExtractDictionaryKey(typeof(LuaUserData)), new ExtractValue(GetAsUserdata));
extractNetObject = new ExtractValue (GetAsNetObject);
}
/*
* Checks if the value at Lua stack index stackPos matches paramType,
* returning a conversion function if it does and null otherwise.
*/
internal ExtractValue GetExtractor (ProxyType paramType)
{
return GetExtractor (paramType.UnderlyingSystemType);
}
internal ExtractValue GetExtractor (Type paramType)
{
if (paramType.IsByRef)
paramType = paramType.GetElementType ();
var extractKey = GetExtractDictionaryKey(paramType);
return extractValues.ContainsKey(extractKey) ? extractValues[extractKey] : extractNetObject;
}
internal ExtractValue CheckLuaType (LuaState luaState, int stackPos, Type paramType)
{
var luatype = LuaLib.LuaType (luaState, stackPos);
if (paramType.IsByRef)
paramType = paramType.GetElementType ();
var underlyingType = Nullable.GetUnderlyingType (paramType);
if (underlyingType != null) {
paramType = underlyingType; // Silently convert nullable types to their non null requics
}
var extractKey = GetExtractDictionaryKey (paramType);
bool netParamIsNumeric = paramType == typeof (int) ||
paramType == typeof (uint) ||
paramType == typeof (long) ||
paramType == typeof (ulong) ||
paramType == typeof (short) ||
paramType == typeof (ushort) ||
paramType == typeof (float) ||
paramType == typeof (double) ||
paramType == typeof (decimal) ||
paramType == typeof (byte);
// If it is a nullable
if (underlyingType != null) {
// null can always be assigned to nullable
if (luatype == LuaTypes.Nil) {
// Return the correct extractor anyways
if (netParamIsNumeric || paramType == typeof (bool))
return extractValues [extractKey];
return extractNetObject;
}
}
if (paramType.Equals (typeof(object)))
return extractValues [extractKey];
//CP: Added support for generic parameters
if (paramType.IsGenericParameter) {
if (luatype == LuaTypes.Boolean)
return extractValues [GetExtractDictionaryKey (typeof(bool))];
else if (luatype == LuaTypes.String)
return extractValues[GetExtractDictionaryKey (typeof(string))];
else if (luatype == LuaTypes.Table)
return extractValues [GetExtractDictionaryKey (typeof(LuaTable))];
else if (luatype == LuaTypes.UserData)
return extractValues [GetExtractDictionaryKey (typeof(object))];
else if (luatype == LuaTypes.Function)
return extractValues [GetExtractDictionaryKey (typeof(LuaFunction))];
else if (luatype == LuaTypes.Number)
return extractValues [GetExtractDictionaryKey (typeof(double))];
}
bool netParamIsString = paramType == typeof (string) || paramType == typeof (char []);
if (netParamIsNumeric) {
if (LuaLib.LuaIsNumber (luaState, stackPos) && !netParamIsString)
return extractValues [extractKey];
} else if (paramType == typeof(bool)) {
if (LuaLib.LuaIsBoolean (luaState, stackPos))
return extractValues [extractKey];
} else if (netParamIsString) {
if (LuaLib.LuaNetIsStringStrict (luaState, stackPos))
return extractValues [extractKey];
else if (luatype == LuaTypes.Nil)
return extractNetObject; // kevinh - silently convert nil to a null string pointer
} else if (paramType == typeof(LuaTable)) {
if (luatype == LuaTypes.Table || luatype == LuaTypes.Nil)
return extractValues [extractKey];
} else if (paramType == typeof(LuaUserData)) {
if (luatype == LuaTypes.UserData || luatype == LuaTypes.Nil)
return extractValues [extractKey];
} else if (paramType == typeof(LuaFunction)) {
if (luatype == LuaTypes.Function || luatype == LuaTypes.Nil)
return extractValues [extractKey];
} else if (typeof(Delegate).IsAssignableFrom (paramType) && luatype == LuaTypes.Function)
return new ExtractValue (new DelegateGenerator (translator, paramType).ExtractGenerated);
else if (paramType.IsInterface() && luatype == LuaTypes.Table)
return new ExtractValue (new ClassGenerator (translator, paramType).ExtractGenerated);
else if ((paramType.IsInterface() || paramType.IsClass()) && luatype == LuaTypes.Nil) {
// kevinh - allow nil to be silently converted to null - extractNetObject will return null when the item ain't found
return extractNetObject;
} else if (LuaLib.LuaType (luaState, stackPos) == LuaTypes.Table) {
if (LuaLib.LuaLGetMetafield (luaState, stackPos, "__index")) {
object obj = translator.GetNetObject (luaState, -1);
LuaLib.LuaSetTop (luaState, -2);
if (obj != null && paramType.IsAssignableFrom (obj.GetType ()))
return extractNetObject;
} else
return null;
} else {
object obj = translator.GetNetObject (luaState, stackPos);
if (obj != null && paramType.IsAssignableFrom (obj.GetType ()))
return extractNetObject;
}
return null;
}
Type GetExtractDictionaryKey(Type targetType)
{
return targetType;
}
/*
* The following functions return the value in the Lua stack
* index stackPos as the desired type if it can, or null
* otherwise.
*/
private object GetAsSbyte (LuaState luaState, int stackPos)
{
sbyte retVal = (sbyte)LuaLib.LuaToNumber (luaState, stackPos);
if (retVal == 0 && !LuaLib.LuaIsNumber (luaState, stackPos))
return null;
return retVal;
}
private object GetAsByte (LuaState luaState, int stackPos)
{
byte retVal = (byte)LuaLib.LuaToNumber (luaState, stackPos);
if (retVal == 0 && !LuaLib.LuaIsNumber (luaState, stackPos))
return null;
return retVal;
}
private object GetAsShort (LuaState luaState, int stackPos)
{
short retVal = (short)LuaLib.LuaToNumber (luaState, stackPos);
if (retVal == 0 && !LuaLib.LuaIsNumber (luaState, stackPos))
return null;
return retVal;
}
private object GetAsUshort (LuaState luaState, int stackPos)
{
ushort retVal = (ushort)LuaLib.LuaToNumber (luaState, stackPos);
if (retVal == 0 && !LuaLib.LuaIsNumber (luaState, stackPos))
return null;
return retVal;
}
private object GetAsInt (LuaState luaState, int stackPos)
{
if (!LuaLib.LuaIsNumber (luaState, stackPos))
return null;
int retVal = (int)LuaLib.LuaToNumber (luaState, stackPos);
return retVal;
}
private object GetAsUint (LuaState luaState, int stackPos)
{
uint retVal = (uint)LuaLib.LuaToNumber (luaState, stackPos);
if (retVal == 0 && !LuaLib.LuaIsNumber (luaState, stackPos))
return null;
return retVal;
}
private object GetAsLong (LuaState luaState, int stackPos)
{
long retVal = (long)LuaLib.LuaToNumber (luaState, stackPos);
if (retVal == 0 && !LuaLib.LuaIsNumber (luaState, stackPos))
return null;
return retVal;
}
private object GetAsUlong (LuaState luaState, int stackPos)
{
ulong retVal = (ulong)LuaLib.LuaToNumber (luaState, stackPos);
if (retVal == 0 && !LuaLib.LuaIsNumber (luaState, stackPos))
return null;
return retVal;
}
private object GetAsDouble (LuaState luaState, int stackPos)
{
double retVal = LuaLib.LuaToNumber (luaState, stackPos);
if (retVal == 0 && !LuaLib.LuaIsNumber (luaState, stackPos))
return null;
return retVal;
}
private object GetAsChar (LuaState luaState, int stackPos)
{
char retVal = (char)LuaLib.LuaToNumber (luaState, stackPos);
if (retVal == 0 && !LuaLib.LuaIsNumber (luaState, stackPos))
return null;
return retVal;
}
private object GetAsFloat (LuaState luaState, int stackPos)
{
float retVal = (float)LuaLib.LuaToNumber (luaState, stackPos);
if (retVal == 0 && !LuaLib.LuaIsNumber (luaState, stackPos))
return null;
return retVal;
}
private object GetAsDecimal (LuaState luaState, int stackPos)
{
decimal retVal = (decimal)LuaLib.LuaToNumber (luaState, stackPos);
if (retVal == 0 && !LuaLib.LuaIsNumber (luaState, stackPos))
return null;
return retVal;
}
private object GetAsBoolean (LuaState luaState, int stackPos)
{
return LuaLib.LuaToBoolean (luaState, stackPos);
}
private object GetAsCharArray (LuaState luaState, int stackPos)
{
if (!LuaLib.LuaNetIsStringStrict (luaState, stackPos))
return null;
string retVal = LuaLib.LuaToString (luaState, stackPos).ToString ();
return retVal.ToCharArray();
}
private object GetAsString (LuaState luaState, int stackPos)
{
if (!LuaLib.LuaNetIsStringStrict (luaState, stackPos))
return null;
string retVal = LuaLib.LuaToString (luaState, stackPos).ToString ();
return retVal;
}
private object GetAsTable (LuaState luaState, int stackPos)
{
return translator.GetTable (luaState, stackPos);
}
private object GetAsFunction (LuaState luaState, int stackPos)
{
return translator.GetFunction (luaState, stackPos);
}
private object GetAsUserdata (LuaState luaState, int stackPos)
{
return translator.GetUserData (luaState, stackPos);
}
public object GetAsObject (LuaState luaState, int stackPos)
{
if (LuaLib.LuaType (luaState, stackPos) == LuaTypes.Table) {
if (LuaLib.LuaLGetMetafield (luaState, stackPos, "__index")) {
if (LuaLib.LuaLCheckMetatable (luaState, -1)) {
LuaLib.LuaInsert (luaState, stackPos);
LuaLib.LuaRemove (luaState, stackPos + 1);
} else
LuaLib.LuaSetTop (luaState, -2);
}
}
object obj = translator.GetObject (luaState, stackPos);
return obj;
}
public object GetAsNetObject (LuaState luaState, int stackPos)
{
object obj = translator.GetNetObject (luaState, stackPos);
if (obj == null && LuaLib.LuaType (luaState, stackPos) == LuaTypes.Table) {
if (LuaLib.LuaLGetMetafield (luaState, stackPos, "__index")) {
if (LuaLib.LuaLCheckMetatable (luaState, -1)) {
LuaLib.LuaInsert (luaState, stackPos);
LuaLib.LuaRemove (luaState, stackPos + 1);
obj = translator.GetNetObject (luaState, stackPos);
} else
LuaLib.LuaSetTop (luaState, -2);
}
}
return obj;
}
}
}
\ No newline at end of file
/*
* This file is part of NLua.
*
* Copyright (c) 2015 Vinicius Jarina (viniciusjarina@gmail.com)
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* 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
* THE SOFTWARE.
*/
using System;
namespace NLua.Config
{
public static class Consts
{
public const string NLuaDescription = "Bridge between the Lua runtime and the CLR";
#if DEBUG
public const string NLuaConfiguration = "Debug";
#else
public const string NLuaConfiguration = "Release";
#endif
public const string NLuaCompany = "NLua.org";
public const string NLuaProduct = "NLua";
public const string NLuaCopyright = "Copyright 2003-2015 Vinicius Jarina , Fabio Mascarenhas, Kevin Hesterm and Megax";
public const string NLuaTrademark = "MIT license";
public const string NLuaVersion = "1.3.2";
public const string NLuaFileVersion = "1.3.2";
}
}
\ No newline at end of file
/*
* This file is part of NLua.
*
* Copyright (c) 2015 Vinicius Jarina (viniciusjarina@gmail.com)
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* 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
* THE SOFTWARE.
*/
using System;
namespace NLua.Event
{
#if USE_KOPILUA
using LuaCore = KopiLua.Lua;
using LuaState = KopiLua.LuaState;
using LuaDebug = KopiLua.LuaDebug;
#else
using LuaCore = KeraLua.Lua;
using LuaState = KeraLua.LuaState;
using LuaDebug = KeraLua.LuaDebug;
#endif
/// <summary>
/// Event args for hook callback event
/// </summary>
/// <author>Reinhard Ostermeier</author>
public class DebugHookEventArgs : EventArgs
{
private readonly LuaDebug luaDebug;
public DebugHookEventArgs (LuaDebug luaDebug)
{
this.luaDebug = luaDebug;
}
public LuaDebug LuaDebug {
get { return luaDebug; }
}
}
}
\ No newline at end of file
/*
* This file is part of NLua.
*
* Copyright (c) 2015 Vinicius Jarina (viniciusjarina@gmail.com)
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* 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
* THE SOFTWARE.
*/
using System;
namespace NLua.Event
{
/// <summary>
/// Event codes for lua hook function
/// </summary>
/// <remarks>
/// Do not change any of the values because they must match the lua values
/// </remarks>
public enum EventCodes
{
LUA_HOOKCALL = 0,
LUA_HOOKRET = 1,
LUA_HOOKLINE = 2,
LUA_HOOKCOUNT = 3,
LUA_HOOKTAILRET = 4
}
}
\ No newline at end of file
/*
* This file is part of NLua.
*
* Copyright (c) 2015 Vinicius Jarina (viniciusjarina@gmail.com)
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* 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
* THE SOFTWARE.
*/
using System;
namespace NLua.Event
{
/// <summary>
/// Event masks for lua hook callback
/// </summary>
/// <remarks>
/// Do not change any of the values because they must match the lua values
/// </remarks>
[Flags]
public enum EventMasks
{
LUA_MASKCALL = (1 << EventCodes.LUA_HOOKCALL),
LUA_MASKRET = (1 << EventCodes.LUA_HOOKRET),
LUA_MASKLINE = (1 << EventCodes.LUA_HOOKLINE),
LUA_MASKCOUNT = (1 << EventCodes.LUA_HOOKCOUNT),
LUA_MASKALL = Int32.MaxValue
}
}
\ No newline at end of file
/*
* This file is part of NLua.
*
* Copyright (c) 2015 Vinicius Jarina (viniciusjarina@gmail.com)
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* 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
* THE SOFTWARE.
*/
using System;
namespace NLua.Event
{
public class HookExceptionEventArgs : EventArgs
{
private readonly Exception m_Exception;
public Exception Exception {
get { return m_Exception; }
}
public HookExceptionEventArgs (Exception ex)
{
m_Exception = ex;
}
}
}
\ No newline at end of file
/*
* This file is part of NLua.
*
* Copyright (c) 2015 Vinicius Jarina (viniciusjarina@gmail.com)
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* 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
* THE SOFTWARE.
*/
using System;
#if !SILVERLIGHT && !NETFX_CORE
using System.Runtime.Serialization;
#endif
namespace NLua.Exceptions
{
/// <summary>
/// Exceptions thrown by the Lua runtime
/// </summary>
#if !SILVERLIGHT && !NETFX_CORE
[Serializable]
#endif
public class LuaException : Exception
{
public LuaException ()
{
}
public LuaException (string message) : base(message)
{
}
public LuaException (string message, Exception innerException) : base(message, innerException)
{
}
#if !SILVERLIGHT && !NETFX_CORE
protected LuaException (SerializationInfo info, StreamingContext context) : base(info, context)
{
}
#endif
}
}
\ No newline at end of file
/*
* This file is part of NLua.
*
* Copyright (c) 2015 Vinicius Jarina (viniciusjarina@gmail.com)
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* 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
* THE SOFTWARE.
*/
using System;
namespace NLua.Exceptions
{
/// <summary>
/// Exceptions thrown by the Lua runtime because of errors in the script
/// </summary>
///
#if !SILVERLIGHT && !NETFX_CORE
[Serializable]
#endif
public class LuaScriptException : LuaException
{
/// <summary>
/// Returns true if the exception has occured as the result of a .NET exception in user code
/// </summary>
public bool IsNetException { get; private set; }
private readonly string source;
/// <summary>
/// The position in the script where the exception was triggered.
/// </summary>
#if SILVERLIGHT && !WINDOWS_PHONE
public string Source { get { return source; } }
#else
public override string Source { get { return source; } }
#endif
/// <summary>
/// Creates a new Lua-only exception.
/// </summary>
/// <param name="message">The message that describes the error.</param>
/// <param name="source">The position in the script where the exception was triggered.</param>
public LuaScriptException (string message, string source) : base(message)
{
this.source = source;
}
/// <summary>
/// Creates a new .NET wrapping exception.
/// </summary>
/// <param name="innerException">The .NET exception triggered by user-code.</param>
/// <param name="source">The position in the script where the exception was triggered.</param>
public LuaScriptException (Exception innerException, string source)
: base("A .NET exception occured in user-code", innerException)
{
this.source = source;
this.IsNetException = true;
}
public override string ToString ()
{
// Prepend the error source
return GetType ().FullName + ": " + source + Message;
}
}
}
\ No newline at end of file
/*
* This file is part of NLua.
*
* Copyright (c) 2015 Vinicius Jarina (viniciusjarina@gmail.com)
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* 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
* THE SOFTWARE.
*/
using System;
using System.Linq;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace NLua.Extensions
{
/// <summary>
/// Some random extension stuff.
/// </summary>
static class CheckNull
{
/// <summary>
/// Determines whether the specified obj is null.
/// </summary>
/// <param name="obj">The obj.</param>
/// <returns>
/// <c>true</c> if the specified obj is null; otherwise, <c>false</c>.
/// </returns>
///
#if USE_KOPILUA
public static bool IsNull (object obj)
{
return (obj == null);
}
#else
public static bool IsNull (IntPtr ptr)
{
return (ptr.Equals (IntPtr.Zero));
}
#endif
}
static class TypeExtensions
{
public static bool HasMethod (this Type t, string name)
{
var op = t.GetMethods (BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
return op.Any (m => m.Name == name);
}
public static bool HasAdditionOpertator (this Type t)
{
if (t.IsPrimitive ())
return true;
return t.HasMethod ("op_Addition");
}
public static bool HasSubtractionOpertator (this Type t)
{
if (t.IsPrimitive ())
return true;
return t.HasMethod ("op_Subtraction");
}
public static bool HasMultiplyOpertator (this Type t)
{
if (t.IsPrimitive ())
return true;
return t.HasMethod ("op_Multiply");
}
public static bool HasDivisionOpertator (this Type t)
{
if (t.IsPrimitive ())
return true;
return t.HasMethod ("op_Division");
}
public static bool HasModulusOpertator (this Type t)
{
if (t.IsPrimitive ())
return true;
return t.HasMethod ("op_Modulus");
}
public static bool HasUnaryNegationOpertator (this Type t)
{
if (t.IsPrimitive ())
return true;
// Unary - will always have only one version.
var op = t.GetMethod ("op_UnaryNegation", BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
return op != null;
}
public static bool HasEqualityOpertator (this Type t)
{
if (t.IsPrimitive ())
return true;
return t.HasMethod ("op_Equality");
}
public static bool HasLessThanOpertator (this Type t)
{
if (t.IsPrimitive ())
return true;
return t.HasMethod ("op_LessThan");
}
public static bool HasLessThanOrEqualOpertator (this Type t)
{
if (t.IsPrimitive ())
return true;
return t.HasMethod ("op_LessThanOrEqual");
}
public static MethodInfo [] GetMethods (this Type t, string name, BindingFlags flags)
{
return t.GetMethods (flags).Where (m => m.Name == name).ToArray ();
}
public static MethodInfo [] GetExtensionMethods (this Type type, IEnumerable<Assembly> assemblies = null)
{
List<Type> types = new List<Type> ();
types.AddRange (type.GetAssembly().GetTypes ().Where (t => t.IsPublic ()));
if (assemblies != null) {
foreach (Assembly item in assemblies) {
if (item == type.GetAssembly ())
continue;
types.AddRange (item.GetTypes ().Where (t => t.IsPublic ()));
}
}
var query = from extensionType in types
where extensionType.IsSealed() && !extensionType.IsGenericType() && !extensionType.IsNested
from method in extensionType.GetMethods (BindingFlags.Static | BindingFlags.Public)
where method.IsDefined (typeof (ExtensionAttribute), false)
where (method.GetParameters()[0].ParameterType == type
|| type.IsSubclassOf(method.GetParameters()[0].ParameterType)
|| type.GetInterfaces().Contains(method.GetParameters()[0].ParameterType))
select method;
return query.ToArray<MethodInfo> ();
}
/// <summary>
/// Extends the System.Type-type to search for a given extended MethodeName.
/// </summary>
/// <param name="MethodeName">Name of the Methode</param>
/// <returns>the found Method or null</returns>
public static MethodInfo GetExtensionMethod (this Type t, string name, IEnumerable<Assembly> assemblies = null)
{
var mi = from methode in t.GetExtensionMethods (assemblies)
where methode.Name == name
select methode;
if (!mi.Any<MethodInfo> ())
return null;
else
return mi.First<MethodInfo> ();
}
public static bool IsPrimitive (this Type t)
{
#if NETFX_CORE
return t.GetTypeInfo ().IsPrimitive;
#else
return t.IsPrimitive;
#endif
}
public static bool IsClass (this Type t)
{
#if NETFX_CORE
return t.GetTypeInfo ().IsClass;
#else
return t.IsClass;
#endif
}
public static bool IsEnum (this Type t)
{
#if NETFX_CORE
return t.GetTypeInfo ().IsEnum;
#else
return t.IsEnum;
#endif
}
public static bool IsPublic (this Type t)
{
#if NETFX_CORE
return t.GetTypeInfo ().IsPublic;
#else
return t.IsPublic;
#endif
}
public static bool IsSealed (this Type t)
{
#if NETFX_CORE
return t.GetTypeInfo ().IsSealed;
#else
return t.IsSealed;
#endif
}
public static bool IsGenericType (this Type t)
{
#if NETFX_CORE
return t.GetTypeInfo ().IsGenericType;
#else
return t.IsGenericType;
#endif
}
public static bool IsInterface (this Type t)
{
#if NETFX_CORE
return t.GetTypeInfo ().IsInterface;
#else
return t.IsInterface;
#endif
}
public static Assembly GetAssembly (this Type t)
{
#if NETFX_CORE
return t.GetTypeInfo ().Assembly;
#else
return t.Assembly;
#endif
}
#if NETFX_CORE
// Missing Reflection methods from WinRT
public const BindingFlags Default = BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance;
public static MethodInfo GetMethod (this Type type, string name, BindingFlags flags, Type [] signature)
{
return GetMethods (type, flags).FirstOrDefault (c => c.Name == name && c.GetParameters ().Select (p => p.ParameterType).SequenceEqual (signature));
}
static IEnumerable<Type> GetTypes (this Assembly assembly)
{
return assembly.ExportedTypes;
}
public static bool IsAssignableFrom (this Type t, Type t2)
{
return t.GetTypeInfo ().IsAssignableFrom (t2.GetTypeInfo ());
}
public static MemberInfo [] GetMember (this Type type, string name, BindingFlags flags)
{
return GetMembers (type, flags).Where (m => m.Name == name).ToArray ();
}
public static MemberInfo [] GetMembers (this Type type, BindingFlags flags)
{
// Metro does have DeclaredMembers but nothing otherwise
return GetEvents (type, flags).Cast<MemberInfo> ()
.Concat (GetFields (type, flags).Cast<MemberInfo> ())
.Concat (GetMethods (type, flags).Cast<MemberInfo> ())
.Concat (GetProperties (type, flags).Cast<MemberInfo> ())
.ToArray ();
}
public static MethodInfo GetMethod (this Type type, string name)
{
return GetMethod (type, name, Default);
}
public static MethodInfo GetMethod (this Type type, string name, BindingFlags flags)
{
return GetMethods (type, flags).FirstOrDefault (m => m.Name == name);
}
public static MethodInfo [] GetMethods (this Type type)
{
return GetMethods (type, Default);
}
public static MethodInfo [] GetMethods (this Type type, BindingFlags flags)
{
var methods = type.GetRuntimeMethods ();
return methods.Where (m =>
((flags.HasFlag (BindingFlags.Static) == m.IsStatic) || (flags.HasFlag (BindingFlags.Instance) == !m.IsStatic)
) &&
(flags.HasFlag (BindingFlags.Public) == m.IsPublic)
).ToArray ();
}
public static PropertyInfo [] GetProperties (this Type type, BindingFlags flags)
{
var props = type.GetRuntimeProperties ();
return props.Where (p =>
((flags.HasFlag (BindingFlags.Static) == (p.GetMethod != null && p.GetMethod.IsStatic)) ||
(flags.HasFlag (BindingFlags.Instance) == (p.GetMethod != null && !p.GetMethod.IsStatic))
) &&
(flags.HasFlag (BindingFlags.Public) == (p.GetMethod != null && p.GetMethod.IsPublic)
)).ToArray ();
}
public static ConstructorInfo GetConstructor (this Type type, Type [] paramTypes)
{
return GetConstructors (type, Default).FirstOrDefault (c => c.GetParameters ().Select (p => p.ParameterType).SequenceEqual (paramTypes));
}
public static ConstructorInfo [] GetConstructors (this Type type)
{
return GetConstructors (type, Default);
}
public static ConstructorInfo [] GetConstructors (this Type type, BindingFlags flags)
{
var props = type.GetTypeInfo ().DeclaredConstructors;
return props.Where (p =>
((flags.HasFlag (BindingFlags.Static) == p.IsStatic) ||
(flags.HasFlag (BindingFlags.Instance) == !p.IsStatic)
) &&
(flags.HasFlag (BindingFlags.Public) == p.IsPublic)
).ToArray ();
}
public static EventInfo [] GetEvents (this Type type, BindingFlags flags)
{
var props = type.GetRuntimeEvents ();
return props.Where (p =>
((flags.HasFlag (BindingFlags.Static) == p.AddMethod.IsStatic) ||
(flags.HasFlag (BindingFlags.Instance) == !p.AddMethod.IsStatic)
) &&
(flags.HasFlag (BindingFlags.Public) == p.AddMethod.IsPublic)
).ToArray ();
}
public static FieldInfo GetField (this Type type, string name)
{
return GetField (type, name, Default);
}
public static FieldInfo GetField (this Type type, string name, BindingFlags flags)
{
return GetFields (type, flags).FirstOrDefault (f => f.Name == name);
}
public static FieldInfo [] GetFields (this Type type, BindingFlags flags)
{
var fields = type.GetRuntimeFields ();
return fields.Where (p =>
((flags.HasFlag (BindingFlags.Static) == p.IsStatic) || (flags.HasFlag (BindingFlags.Instance) == !p.IsStatic)
) &&
(flags.HasFlag (BindingFlags.Public) == p.IsPublic)
).ToArray ();
}
public static bool ImplementInterface (this Type t, string name)
{
return t.GetTypeInfo ().ImplementedInterfaces.Any (i => i.Name == name);
}
#endif
}
static class StringExtensions
{
public static IEnumerable<string> SplitWithEscape (this string input, char separator, char escapeCharacter)
{
int start = 0;
int index = 0;
while (index < input.Length) {
index = input.IndexOf (separator, index);
if (index == -1)
break;
if (input [index - 1] == escapeCharacter) {
input = input.Remove (index - 1, 1);
continue;
}
yield return input.Substring (start, index - start);
index++;
start = index;
}
yield return input.Substring (start);
}
}
}
\ No newline at end of file
/*
* This file is part of NLua.
*
* Copyright (c) 2015 Vinicius Jarina (viniciusjarina@gmail.com)
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* 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
* THE SOFTWARE.
*/
using System;
namespace NLua
{
#if USE_KOPILUA
using LuaCore = KopiLua.Lua;
using LuaState = KopiLua.LuaState;
#else
using LuaCore = KeraLua.Lua;
using LuaState = KeraLua.LuaState;
#endif
/*
* Class used for generating delegates that get a table from the Lua
* stack as a an object of a specific type.
*
* Author: Fabio Mascarenhas
* Version: 1.0
*/
class ClassGenerator
{
private ObjectTranslator translator;
private Type klass;
public ClassGenerator (ObjectTranslator objTranslator, Type typeClass)
{
translator = objTranslator;
klass = typeClass;
}
public object ExtractGenerated (LuaState luaState, int stackPos)
{
return CodeGeneration.Instance.GetClassInstance (klass, translator.GetTable (luaState, stackPos));
}
}
}
\ No newline at end of file
/*
* This file is part of NLua.
*
* Copyright (c) 2015 Vinicius Jarina (viniciusjarina@gmail.com)
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* 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
* THE SOFTWARE.
*/
using System;
using System.Linq;
using System.Threading;
using System.Reflection;
using NLua.Extensions;
#if !MONOTOUCH
using System.Reflection.Emit;
#endif
using System.Collections;
using System.Collections.Generic;
using NLua.Method;
namespace NLua
{
/*
* Dynamically generates new types from existing types and
* Lua function and table values. Generated types are event handlers,
* delegates, interface implementations and subclasses.
*
* Author: Fabio Mascarenhas
* Version: 1.0
*/
class CodeGeneration
{
private Dictionary<Type, LuaClassType> classCollection = new Dictionary<Type, LuaClassType> ();
private Dictionary<Type, Type> delegateCollection = new Dictionary<Type, Type> ();
private static readonly CodeGeneration instance = new CodeGeneration ();
private AssemblyName assemblyName;
#if !MONOTOUCH && !SILVERLIGHT && !NETFX_CORE
private Dictionary<Type, Type> eventHandlerCollection = new Dictionary<Type, Type> ();
private Type eventHandlerParent = typeof(LuaEventHandler);
private Type delegateParent = typeof(LuaDelegate);
private Type classHelper = typeof(LuaClassHelper);
private AssemblyBuilder newAssembly;
private ModuleBuilder newModule;
private int luaClassNumber = 1;
#endif
static CodeGeneration ()
{
}
private CodeGeneration ()
{
// Create an assembly name
assemblyName = new AssemblyName ();
assemblyName.Name = "NLua_generatedcode";
// Create a new assembly with one module.
#if !MONOTOUCH && !SILVERLIGHT && !NETFX_CORE
newAssembly = Thread.GetDomain ().DefineDynamicAssembly (assemblyName, AssemblyBuilderAccess.Run);
newModule = newAssembly.DefineDynamicModule ("NLua_generatedcode");
#endif
}
/*
* Singleton instance of the class
*/
public static CodeGeneration Instance {
get { return instance; }
}
/*
* Generates an event handler that calls a Lua function
*/
private Type GenerateEvent (Type eventHandlerType)
{
#if MONOTOUCH
throw new NotImplementedException (" Emit not available on MonoTouch ");
#elif SILVERLIGHT
throw new NotImplementedException(" Emit not available on Silverlight ");
#elif NETFX_CORE
throw new NotImplementedException(" Emit not available on Windows Store ");
#else
string typeName;
lock (this) {
typeName = "LuaGeneratedClass" + luaClassNumber.ToString ();
luaClassNumber++;
}
// Define a public class in the assembly, called typeName
var myType = newModule.DefineType (typeName, TypeAttributes.Public, eventHandlerParent);
// Defines the handler method. Its signature is void(object, <subclassofEventArgs>)
var paramTypes = new Type[2];
paramTypes [0] = typeof(object);
paramTypes [1] = eventHandlerType;
var returnType = typeof(void);
var handleMethod = myType.DefineMethod ("HandleEvent", MethodAttributes.Public | MethodAttributes.HideBySig, returnType, paramTypes);
// Emits the IL for the method. It loads the arguments
// and calls the handleEvent method of the base class
ILGenerator generator = handleMethod.GetILGenerator ();
generator.Emit (OpCodes.Ldarg_0);
generator.Emit (OpCodes.Ldarg_1);
generator.Emit (OpCodes.Ldarg_2);
var miGenericEventHandler = eventHandlerParent.GetMethod ("HandleEvent");
generator.Emit (OpCodes.Call, miGenericEventHandler);
// returns
generator.Emit (OpCodes.Ret);
// creates the new type
return myType.CreateType ();
#endif
}
/*
* Generates a type that can be used for instantiating a delegate
* of the provided type, given a Lua function.
*/
private Type GenerateDelegate (Type delegateType)
{
#if MONOTOUCH
throw new NotImplementedException ("GenerateDelegate is not available on iOS, please register your LuaDelegate type with Lua.RegisterLuaDelegateType( yourDelegate, theLuaDelegateHandler) ");
#elif SILVERLIGHT
throw new NotImplementedException("GenerateDelegate is not available on Silverlight, please register your LuaDelegate type with Lua.RegisterLuaDelegateType( yourDelegate, theLuaDelegateHandler) ");
#elif NETFX_CORE
throw new NotImplementedException("GenerateDelegate is not available on Windows Store, please register your LuaDelegate type with Lua.RegisterLuaDelegateType( yourDelegate, theLuaDelegateHandler) ");
#else
string typeName;
lock (this) {
typeName = "LuaGeneratedClass" + luaClassNumber.ToString ();
luaClassNumber++;
}
// Define a public class in the assembly, called typeName
var myType = newModule.DefineType (typeName, TypeAttributes.Public, delegateParent);
// Defines the delegate method with the same signature as the
// Invoke method of delegateType
var invokeMethod = delegateType.GetMethod ("Invoke");
var paramInfo = invokeMethod.GetParameters ();
var paramTypes = new Type[paramInfo.Length];
var returnType = invokeMethod.ReturnType;
// Counts out and ref params, for use later
int nOutParams = 0;
int nOutAndRefParams = 0;
for (int i = 0; i < paramTypes.Length; i++) {
paramTypes [i] = paramInfo [i].ParameterType;
if ((!paramInfo [i].IsIn) && paramInfo [i].IsOut)
nOutParams++;
if (paramTypes [i].IsByRef)
nOutAndRefParams++;
}
int[] refArgs = new int[nOutAndRefParams];
var delegateMethod = myType.DefineMethod ("CallFunction", invokeMethod.Attributes, returnType, paramTypes);
// Generates the IL for the method
ILGenerator generator = delegateMethod.GetILGenerator ();
generator.DeclareLocal (typeof(object[])); // original arguments
generator.DeclareLocal (typeof(object[])); // with out-only arguments removed
generator.DeclareLocal (typeof(int[])); // indexes of out and ref arguments
if (!(returnType == typeof(void))) // return value
generator.DeclareLocal (returnType);
else
generator.DeclareLocal (typeof(object));
// Initializes local variables
generator.Emit (OpCodes.Ldc_I4, paramTypes.Length);
generator.Emit (OpCodes.Newarr, typeof(object));
generator.Emit (OpCodes.Stloc_0);
generator.Emit (OpCodes.Ldc_I4, paramTypes.Length - nOutParams);
generator.Emit (OpCodes.Newarr, typeof(object));
generator.Emit (OpCodes.Stloc_1);
generator.Emit (OpCodes.Ldc_I4, nOutAndRefParams);
generator.Emit (OpCodes.Newarr, typeof(int));
generator.Emit (OpCodes.Stloc_2);
// Stores the arguments in the local variables
for (int iArgs = 0, iInArgs = 0, iOutArgs = 0; iArgs < paramTypes.Length; iArgs++) {
generator.Emit (OpCodes.Ldloc_0);
generator.Emit (OpCodes.Ldc_I4, iArgs);
generator.Emit (OpCodes.Ldarg, iArgs + 1);
if (paramTypes [iArgs].IsByRef) {
if (paramTypes [iArgs].GetElementType ().IsValueType) {
generator.Emit (OpCodes.Ldobj, paramTypes [iArgs].GetElementType ());
generator.Emit (OpCodes.Box, paramTypes [iArgs].GetElementType ());
} else
generator.Emit (OpCodes.Ldind_Ref);
} else {
if (paramTypes [iArgs].IsValueType)
generator.Emit (OpCodes.Box, paramTypes [iArgs]);
}
generator.Emit (OpCodes.Stelem_Ref);
if (paramTypes [iArgs].IsByRef) {
generator.Emit (OpCodes.Ldloc_2);
generator.Emit (OpCodes.Ldc_I4, iOutArgs);
generator.Emit (OpCodes.Ldc_I4, iArgs);
generator.Emit (OpCodes.Stelem_I4);
refArgs [iOutArgs] = iArgs;
iOutArgs++;
}
if (paramInfo [iArgs].IsIn || (!paramInfo [iArgs].IsOut)) {
generator.Emit (OpCodes.Ldloc_1);
generator.Emit (OpCodes.Ldc_I4, iInArgs);
generator.Emit (OpCodes.Ldarg, iArgs + 1);
if (paramTypes [iArgs].IsByRef) {
if (paramTypes [iArgs].GetElementType ().IsValueType) {
generator.Emit (OpCodes.Ldobj, paramTypes [iArgs].GetElementType ());
generator.Emit (OpCodes.Box, paramTypes [iArgs].GetElementType ());
} else
generator.Emit (OpCodes.Ldind_Ref);
} else {
if (paramTypes [iArgs].IsValueType)
generator.Emit (OpCodes.Box, paramTypes [iArgs]);
}
generator.Emit (OpCodes.Stelem_Ref);
iInArgs++;
}
}
// Calls the callFunction method of the base class
generator.Emit (OpCodes.Ldarg_0);
generator.Emit (OpCodes.Ldloc_0);
generator.Emit (OpCodes.Ldloc_1);
generator.Emit (OpCodes.Ldloc_2);
var miGenericEventHandler = delegateParent.GetMethod ("CallFunction");
generator.Emit (OpCodes.Call, miGenericEventHandler);
// Stores return value
if (returnType == typeof(void)) {
generator.Emit (OpCodes.Pop);
generator.Emit (OpCodes.Ldnull);
} else if (returnType.IsValueType) {
generator.Emit (OpCodes.Unbox, returnType);
generator.Emit (OpCodes.Ldobj, returnType);
} else
generator.Emit (OpCodes.Castclass, returnType);
generator.Emit (OpCodes.Stloc_3);
// Stores new value of out and ref params
for (int i = 0; i < refArgs.Length; i++) {
generator.Emit (OpCodes.Ldarg, refArgs [i] + 1);
generator.Emit (OpCodes.Ldloc_0);
generator.Emit (OpCodes.Ldc_I4, refArgs [i]);
generator.Emit (OpCodes.Ldelem_Ref);
if (paramTypes [refArgs [i]].GetElementType ().IsValueType) {
generator.Emit (OpCodes.Unbox, paramTypes [refArgs [i]].GetElementType ());
generator.Emit (OpCodes.Ldobj, paramTypes [refArgs [i]].GetElementType ());
generator.Emit (OpCodes.Stobj, paramTypes [refArgs [i]].GetElementType ());
} else {
generator.Emit (OpCodes.Castclass, paramTypes [refArgs [i]].GetElementType ());
generator.Emit (OpCodes.Stind_Ref);
}
}
// Returns
if (!(returnType == typeof(void)))
generator.Emit (OpCodes.Ldloc_3);
generator.Emit (OpCodes.Ret);
return myType.CreateType (); // creates the new type
#endif
}
void GetReturnTypesFromClass (Type klass, out Type[][] returnTypes)
{
var classMethods = klass.GetMethods ();
returnTypes = new Type[classMethods.Length][];
int i = 0;
foreach (var method in classMethods) {
if (klass.IsInterface ()) {
GetReturnTypesFromMethod (method, out returnTypes [i]);
i++;
} else {
if (!method.IsPrivate && !method.IsFinal && method.IsVirtual) {
GetReturnTypesFromMethod (method, out returnTypes [i]);
i++;
}
}
}
}
/*
* Generates an implementation of klass, if it is an interface, or
* a subclass of klass that delegates its virtual methods to a Lua table.
*/
public void GenerateClass (Type klass, out Type newType, out Type[][] returnTypes)
{
#if MONOTOUCH
throw new NotImplementedException (" Emit not available on MonoTouch ");
#elif SILVERLIGHT
throw new NotImplementedException (" Emit not available on Silverlight ");
#elif NETFX_CORE
throw new NotImplementedException (" Emit not available on Windows Store ");
#else
string typeName;
lock (this) {
typeName = "LuaGeneratedClass" + luaClassNumber.ToString ();
luaClassNumber++;
}
TypeBuilder myType;
// Define a public class in the assembly, called typeName
if (klass.IsInterface)
myType = newModule.DefineType (typeName, TypeAttributes.Public, typeof(object), new Type[] {
klass,
typeof(ILuaGeneratedType)
});
else
myType = newModule.DefineType (typeName, TypeAttributes.Public, klass, new Type[] { typeof(ILuaGeneratedType) });
// Field that stores the Lua table
var luaTableField = myType.DefineField ("__luaInterface_luaTable", typeof(LuaTable), FieldAttributes.Public);
// Field that stores the return types array
var returnTypesField = myType.DefineField ("__luaInterface_returnTypes", typeof(Type[][]), FieldAttributes.Public);
// Generates the constructor for the new type, it takes a Lua table and an array
// of return types and stores them in the respective fields
var constructor = myType.DefineConstructor (MethodAttributes.Public, CallingConventions.Standard, new Type[] {
typeof(LuaTable),
typeof(Type[][])
});
ILGenerator generator = constructor.GetILGenerator ();
generator.Emit (OpCodes.Ldarg_0);
if (klass.IsInterface)
generator.Emit (OpCodes.Call, typeof(object).GetConstructor (Type.EmptyTypes));
else
generator.Emit (OpCodes.Call, klass.GetConstructor (Type.EmptyTypes));
generator.Emit (OpCodes.Ldarg_0);
generator.Emit (OpCodes.Ldarg_1);
generator.Emit (OpCodes.Stfld, luaTableField);
generator.Emit (OpCodes.Ldarg_0);
generator.Emit (OpCodes.Ldarg_2);
generator.Emit (OpCodes.Stfld, returnTypesField);
generator.Emit (OpCodes.Ret);
// Generates overriden versions of the klass' public virtual methods
var classMethods = klass.GetMethods ();
returnTypes = new Type[classMethods.Length][];
int i = 0;
foreach (var method in classMethods) {
if (klass.IsInterface) {
GenerateMethod (myType, method, MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.NewSlot,
i, luaTableField, returnTypesField, false, out returnTypes [i]);
i++;
} else {
if (!method.IsPrivate && !method.IsFinal && method.IsVirtual) {
GenerateMethod (myType, method, (method.Attributes | MethodAttributes.NewSlot) ^ MethodAttributes.NewSlot, i,
luaTableField, returnTypesField, true, out returnTypes [i]);
i++;
}
}
}
// Generates an implementation of the luaInterfaceGetLuaTable method
var returnTableMethod = myType.DefineMethod ("LuaInterfaceGetLuaTable",
MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual, typeof(LuaTable), new Type[0]);
myType.DefineMethodOverride (returnTableMethod, typeof(ILuaGeneratedType).GetMethod ("LuaInterfaceGetLuaTable"));
generator = returnTableMethod.GetILGenerator ();
generator.Emit (OpCodes.Ldfld, luaTableField);
generator.Emit (OpCodes.Ret);
newType = myType.CreateType (); // Creates the type
#endif
}
void GetReturnTypesFromMethod (MethodInfo method, out Type[] returnTypes)
{
var paramInfo = method.GetParameters ();
var paramTypes = new Type[paramInfo.Length];
var returnTypesList = new List<Type> ();
// Counts out and ref parameters, for later use,
// and creates the list of return types
int nOutParams = 0;
int nOutAndRefParams = 0;
var returnType = method.ReturnType;
returnTypesList.Add (returnType);
for (int i = 0; i < paramTypes.Length; i++) {
paramTypes [i] = paramInfo [i].ParameterType;
#if SILVERLIGHT
if (paramInfo[i].IsOut) {
#else
if ((!paramInfo [i].IsIn) && paramInfo [i].IsOut) {
#endif
nOutParams++;
}
if (paramTypes [i].IsByRef) {
returnTypesList.Add (paramTypes [i].GetElementType ());
nOutAndRefParams++;
}
}
returnTypes = returnTypesList.ToArray ();
}
#if !MONOTOUCH && !SILVERLIGHT && !NETFX_CORE
/*
* Generates an overriden implementation of method inside myType that delegates
* to a function in a Lua table with the same name, if the function exists. If it
* doesn't the method calls the base method (or does nothing, in case of interface
* implementations).
*/
private void GenerateMethod (TypeBuilder myType, MethodInfo method, MethodAttributes attributes, int methodIndex,
FieldInfo luaTableField, FieldInfo returnTypesField, bool generateBase, out Type[] returnTypes)
{
var paramInfo = method.GetParameters ();
var paramTypes = new Type[paramInfo.Length];
var returnTypesList = new List<Type> ();
// Counts out and ref parameters, for later use,
// and creates the list of return types
int nOutParams = 0;
int nOutAndRefParams = 0;
var returnType = method.ReturnType;
returnTypesList.Add (returnType);
for (int i = 0; i < paramTypes.Length; i++) {
paramTypes [i] = paramInfo [i].ParameterType;
if ((!paramInfo [i].IsIn) && paramInfo [i].IsOut)
nOutParams++;
if (paramTypes [i].IsByRef) {
returnTypesList.Add (paramTypes [i].GetElementType ());
nOutAndRefParams++;
}
}
int[] refArgs = new int[nOutAndRefParams];
returnTypes = returnTypesList.ToArray ();
// Generates a version of the method that calls the base implementation
// directly, for use by the base field of the table
if (generateBase) {
var baseMethod = myType.DefineMethod ("__luaInterface_base_" + method.Name,
MethodAttributes.Private | MethodAttributes.NewSlot | MethodAttributes.HideBySig,
returnType, paramTypes);
ILGenerator generatorBase = baseMethod.GetILGenerator ();
generatorBase.Emit (OpCodes.Ldarg_0);
for (int i = 0; i < paramTypes.Length; i++)
generatorBase.Emit (OpCodes.Ldarg, i + 1);
generatorBase.Emit (OpCodes.Call, method);
if (returnType == typeof(void))
generatorBase.Emit (OpCodes.Pop);
generatorBase.Emit (OpCodes.Ret);
}
// Defines the method
var methodImpl = myType.DefineMethod (method.Name, attributes, returnType, paramTypes);
// If it's an implementation of an interface tells what method it
// is overriding
if (myType.BaseType.Equals (typeof(object)))
myType.DefineMethodOverride (methodImpl, method);
ILGenerator generator = methodImpl.GetILGenerator ();
generator.DeclareLocal (typeof(object[])); // original arguments
generator.DeclareLocal (typeof(object[])); // with out-only arguments removed
generator.DeclareLocal (typeof(int[])); // indexes of out and ref arguments
if (!(returnType == typeof(void))) // return value
generator.DeclareLocal (returnType);
else
generator.DeclareLocal (typeof(object));
// Initializes local variables
generator.Emit (OpCodes.Ldc_I4, paramTypes.Length);
generator.Emit (OpCodes.Newarr, typeof(object));
generator.Emit (OpCodes.Stloc_0);
generator.Emit (OpCodes.Ldc_I4, paramTypes.Length - nOutParams + 1);
generator.Emit (OpCodes.Newarr, typeof(object));
generator.Emit (OpCodes.Stloc_1);
generator.Emit (OpCodes.Ldc_I4, nOutAndRefParams);
generator.Emit (OpCodes.Newarr, typeof(int));
generator.Emit (OpCodes.Stloc_2);
generator.Emit (OpCodes.Ldloc_1);
generator.Emit (OpCodes.Ldc_I4_0);
generator.Emit (OpCodes.Ldarg_0);
generator.Emit (OpCodes.Ldfld, luaTableField);
generator.Emit (OpCodes.Stelem_Ref);
// Stores the arguments into the local variables, as needed
for (int iArgs = 0, iInArgs = 1, iOutArgs = 0; iArgs < paramTypes.Length; iArgs++) {
generator.Emit (OpCodes.Ldloc_0);
generator.Emit (OpCodes.Ldc_I4, iArgs);
generator.Emit (OpCodes.Ldarg, iArgs + 1);
if (paramTypes [iArgs].IsByRef) {
if (paramTypes [iArgs].GetElementType ().IsValueType) {
generator.Emit (OpCodes.Ldobj, paramTypes [iArgs].GetElementType ());
generator.Emit (OpCodes.Box, paramTypes [iArgs].GetElementType ());
} else
generator.Emit (OpCodes.Ldind_Ref);
} else {
if (paramTypes [iArgs].IsValueType)
generator.Emit (OpCodes.Box, paramTypes [iArgs]);
}
generator.Emit (OpCodes.Stelem_Ref);
if (paramTypes [iArgs].IsByRef) {
generator.Emit (OpCodes.Ldloc_2);
generator.Emit (OpCodes.Ldc_I4, iOutArgs);
generator.Emit (OpCodes.Ldc_I4, iArgs);
generator.Emit (OpCodes.Stelem_I4);
refArgs [iOutArgs] = iArgs;
iOutArgs++;
}
if (paramInfo [iArgs].IsIn || (!paramInfo [iArgs].IsOut)) {
generator.Emit (OpCodes.Ldloc_1);
generator.Emit (OpCodes.Ldc_I4, iInArgs);
generator.Emit (OpCodes.Ldarg, iArgs + 1);
if (paramTypes [iArgs].IsByRef) {
if (paramTypes [iArgs].GetElementType ().IsValueType) {
generator.Emit (OpCodes.Ldobj, paramTypes [iArgs].GetElementType ());
generator.Emit (OpCodes.Box, paramTypes [iArgs].GetElementType ());
} else
generator.Emit (OpCodes.Ldind_Ref);
} else {
if (paramTypes [iArgs].IsValueType)
generator.Emit (OpCodes.Box, paramTypes [iArgs]);
}
generator.Emit (OpCodes.Stelem_Ref);
iInArgs++;
}
}
// Gets the function the method will delegate to by calling
// the getTableFunction method of class LuaClassHelper
generator.Emit (OpCodes.Ldarg_0);
generator.Emit (OpCodes.Ldfld, luaTableField);
generator.Emit (OpCodes.Ldstr, method.Name);
generator.Emit (OpCodes.Call, classHelper.GetMethod ("GetTableFunction"));
var lab1 = generator.DefineLabel ();
generator.Emit (OpCodes.Dup);
generator.Emit (OpCodes.Brtrue_S, lab1);
// Function does not exist, call base method
generator.Emit (OpCodes.Pop);
if (!method.IsAbstract) {
generator.Emit (OpCodes.Ldarg_0);
for (int i = 0; i < paramTypes.Length; i++)
generator.Emit (OpCodes.Ldarg, i + 1);
generator.Emit (OpCodes.Call, method);
if (returnType == typeof(void))
generator.Emit (OpCodes.Pop);
generator.Emit (OpCodes.Ret);
generator.Emit (OpCodes.Ldnull);
} else
generator.Emit (OpCodes.Ldnull);
var lab2 = generator.DefineLabel ();
generator.Emit (OpCodes.Br_S, lab2);
generator.MarkLabel (lab1);
// Function exists, call using method callFunction of LuaClassHelper
generator.Emit (OpCodes.Ldloc_0);
generator.Emit (OpCodes.Ldarg_0);
generator.Emit (OpCodes.Ldfld, returnTypesField);
generator.Emit (OpCodes.Ldc_I4, methodIndex);
generator.Emit (OpCodes.Ldelem_Ref);
generator.Emit (OpCodes.Ldloc_1);
generator.Emit (OpCodes.Ldloc_2);
generator.Emit (OpCodes.Call, classHelper.GetMethod ("CallFunction"));
generator.MarkLabel (lab2);
// Stores the function return value
if (returnType == typeof(void)) {
generator.Emit (OpCodes.Pop);
generator.Emit (OpCodes.Ldnull);
} else if (returnType.IsValueType) {
generator.Emit (OpCodes.Unbox, returnType);
generator.Emit (OpCodes.Ldobj, returnType);
} else
generator.Emit (OpCodes.Castclass, returnType);
generator.Emit (OpCodes.Stloc_3);
// Sets return values of out and ref parameters
for (int i = 0; i < refArgs.Length; i++) {
generator.Emit (OpCodes.Ldarg, refArgs [i] + 1);
generator.Emit (OpCodes.Ldloc_0);
generator.Emit (OpCodes.Ldc_I4, refArgs [i]);
generator.Emit (OpCodes.Ldelem_Ref);
if (paramTypes [refArgs [i]].GetElementType ().IsValueType) {
generator.Emit (OpCodes.Unbox, paramTypes [refArgs [i]].GetElementType ());
generator.Emit (OpCodes.Ldobj, paramTypes [refArgs [i]].GetElementType ());
generator.Emit (OpCodes.Stobj, paramTypes [refArgs [i]].GetElementType ());
} else {
generator.Emit (OpCodes.Castclass, paramTypes [refArgs [i]].GetElementType ());
generator.Emit (OpCodes.Stind_Ref);
}
}
// Returns
if (!(returnType == typeof(void)))
generator.Emit (OpCodes.Ldloc_3);
generator.Emit (OpCodes.Ret);
}
#endif
/*
* Gets an event handler for the event type that delegates to the eventHandler Lua function.
* Caches the generated type.
*/
public LuaEventHandler GetEvent (Type eventHandlerType, LuaFunction eventHandler)
{
#if MONOTOUCH
throw new NotImplementedException (" Emit not available on MonoTouch ");
#elif SILVERLIGHT
throw new NotImplementedException (" Emit not available on Silverlight ");
#elif NETFX_CORE
throw new NotImplementedException (" Emit not available on Windows Store ");
#else
Type eventConsumerType;
if (eventHandlerCollection.ContainsKey (eventHandlerType))
eventConsumerType = eventHandlerCollection [eventHandlerType];
else {
eventConsumerType = GenerateEvent (eventHandlerType);
eventHandlerCollection [eventHandlerType] = eventConsumerType;
}
var luaEventHandler = (LuaEventHandler)Activator.CreateInstance (eventConsumerType);
luaEventHandler.handler = eventHandler;
return luaEventHandler;
#endif
}
public void RegisterLuaDelegateType (Type delegateType, Type luaDelegateType)
{
delegateCollection [delegateType] = luaDelegateType;
}
public void RegisterLuaClassType (Type klass, Type luaClass)
{
LuaClassType luaClassType = new LuaClassType ();
luaClassType.klass = luaClass;
GetReturnTypesFromClass (klass, out luaClassType.returnTypes);
classCollection [klass] = luaClassType;
}
/*
* Gets a delegate with delegateType that calls the luaFunc Lua function
* Caches the generated type.
*/
public Delegate GetDelegate (Type delegateType, LuaFunction luaFunc)
{
var returnTypes = new List<Type> ();
Type luaDelegateType;
if (delegateCollection.ContainsKey (delegateType))
luaDelegateType = delegateCollection [delegateType];
else {
luaDelegateType = GenerateDelegate (delegateType);
delegateCollection [delegateType] = luaDelegateType;
}
var methodInfo = delegateType.GetMethod ("Invoke");
returnTypes.Add (methodInfo.ReturnType);
foreach (ParameterInfo paramInfo in methodInfo.GetParameters()) {
if (paramInfo.ParameterType.IsByRef)
returnTypes.Add (paramInfo.ParameterType);
}
var luaDelegate = (LuaDelegate)Activator.CreateInstance (luaDelegateType);
luaDelegate.function = luaFunc;
luaDelegate.returnTypes = returnTypes.ToArray ();
#if NETFX_CORE
var mi = luaDelegate.GetType ().GetTypeInfo ().GetDeclaredMethod ("CallFunction");
return mi.CreateDelegate (delegateType, luaDelegate);
#else
return Delegate.CreateDelegate (delegateType, luaDelegate, "CallFunction");
#endif
}
/*
* Gets an instance of an implementation of the klass interface or
* subclass of klass that delegates public virtual methods to the
* luaTable table.
* Caches the generated type.
*/
public object GetClassInstance (Type klass, LuaTable luaTable)
{
LuaClassType luaClassType;
if (classCollection.ContainsKey (klass))
luaClassType = classCollection [klass];
else {
luaClassType = new LuaClassType ();
GenerateClass (klass, out luaClassType.klass, out luaClassType.returnTypes);
classCollection [klass] = luaClassType;
}
return Activator.CreateInstance (luaClassType.klass, new object[] {
luaTable,
luaClassType.returnTypes
});
}
}
}
\ No newline at end of file
/*
* This file is part of NLua.
*
* Copyright (c) 2015 Vinicius Jarina (viniciusjarina@gmail.com)
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* 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
* THE SOFTWARE.
*/
using System;
namespace NLua
{
#if USE_KOPILUA
using LuaCore = KopiLua.Lua;
using LuaState = KopiLua.LuaState;
#else
using LuaCore = KeraLua.Lua;
using LuaState = KeraLua.LuaState;
#endif
/*
* Class used for generating delegates that get a function from the Lua
* stack as a delegate of a specific type.
*
* Author: Fabio Mascarenhas
* Version: 1.0
*/
class DelegateGenerator
{
private ObjectTranslator translator;
private Type delegateType;
public DelegateGenerator (ObjectTranslator objectTranslator, Type type)
{
translator = objectTranslator;
delegateType = type;
}
public object ExtractGenerated (LuaState luaState, int stackPos)
{
return CodeGeneration.Instance.GetDelegate (delegateType, translator.GetFunction (luaState, stackPos));
}
}
}
\ No newline at end of file
/*
* This file is part of NLua.
*
* Copyright (c) 2015 Vinicius Jarina (viniciusjarina@gmail.com)
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* 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
* THE SOFTWARE.
*/
using System;
namespace NLua
{
/*
* Common interface for types generated from tables. The method
* returns the table that overrides some or all of the type's methods.
*/
public interface ILuaGeneratedType
{
LuaTable LuaInterfaceGetLuaTable ();
}
}
\ No newline at end of file
/*
* This file is part of NLua.
*
* Copyright (c) 2015 Vinicius Jarina (viniciusjarina@gmail.com)
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* 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
* THE SOFTWARE.
*/
using System;
namespace NLua
{
/*
* Structure to store a type and the return types of
* its methods (the type of the returned value and out/ref
* parameters).
*/
struct LuaClassType
{
public Type klass;
public Type[][] returnTypes;
}
}
\ No newline at end of file
/*
* This file is part of NLua.
*
* Copyright (c) 2014 Vinicius Jarina (viniciusjarina@gmail.com)
* Copyright (C) 2003-2005 Fabio Mascarenhas de Queiroz.
* Copyright (C) 2012 Megax <http://megax.yeahunter.hu/>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* 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
* THE SOFTWARE.
*/
using System;
using System.IO;
using System.Linq;
using System.Threading;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using NLua.Event;
using NLua.Method;
using NLua.Exceptions;
using NLua.Extensions;
#if MONOTOUCH
using ObjCRuntime;
#endif
namespace NLua
{
#if USE_KOPILUA
using LuaCore = KopiLua.Lua;
using LuaState = KopiLua.LuaState;
using LuaHook = KopiLua.LuaHook;
using LuaDebug = KopiLua.LuaDebug;
using LuaNativeFunction = KopiLua.LuaNativeFunction;
#else
using LuaCore = KeraLua.Lua;
using LuaState = KeraLua.LuaState;
using LuaHook = KeraLua.LuaHook;
using LuaDebug = KeraLua.LuaDebug;
using LuaNativeFunction = KeraLua.LuaNativeFunction;
#endif
/*
* Main class of NLua
* Object-oriented wrapper to Lua API
*
* Author: Fabio Mascarenhas
* Version: 1.0
*
* // steffenj: important changes in Lua class:
* - removed all Open*Lib() functions
* - all libs automatically open in the Lua class constructor (just assign nil to unwanted libs)
* */
[CLSCompliant(true)]
public class Lua : IDisposable
{
#region lua debug functions
/// <summary>
/// Event that is raised when an exception occures during a hook call.
/// </summary>
public event EventHandler<HookExceptionEventArgs> HookException;
/// <summary>
/// Event when lua hook callback is called
/// </summary>
/// <remarks>
/// Is only raised if SetDebugHook is called before.
/// </remarks>
public event EventHandler<DebugHookEventArgs> DebugHook;
/// <summary>
/// lua hook calback delegate
/// </summary>
private LuaHook hookCallback = null;
#endregion
#region Globals auto-complete
private readonly List<string> globals = new List<string> ();
private bool globalsSorted;
#endregion
private LuaState luaState;
/// <summary>
/// True while a script is being executed
/// </summary>
public bool IsExecuting { get { return executing; } }
private LuaNativeFunction panicCallback;
private ObjectTranslator translator;
/// <summary>
/// Used to protect the (global) object translator pool during add/remove
/// </summary>
private static readonly object translatorPoolLock = new object();
/// <summary>
/// Used to ensure multiple .net threads all get serialized by this single lock for access to the lua stack/objects
/// </summary>
//private object luaLock = new object();
private bool _StatePassed;
private bool executing;
static string initLuanet =
@"local metatable = {}
local rawget = rawget
local import_type = luanet.import_type
local load_assembly = luanet.load_assembly
luanet.error, luanet.type = error, type
-- Lookup a .NET identifier component.
function metatable:__index(key) -- key is e.g. 'Form'
-- Get the fully-qualified name, e.g. 'System.Windows.Forms.Form'
local fqn = rawget(self,'.fqn')
fqn = ((fqn and fqn .. '.') or '') .. key
-- Try to find either a luanet function or a CLR type
local obj = rawget(luanet,key) or import_type(fqn)
-- If key is neither a luanet function or a CLR type, then it is simply
-- an identifier component.
if obj == nil then
-- It might be an assembly, so we load it too.
pcall(load_assembly,fqn)
obj = { ['.fqn'] = fqn }
setmetatable(obj, metatable)
end
-- Cache this lookup
rawset(self, key, obj)
return obj
end
-- A non-type has been called; e.g. foo = System.Foo()
function metatable:__call(...)
error('No such type: ' .. rawget(self,'.fqn'), 2)
end
-- This is the root of the .NET namespace
luanet['.fqn'] = false
setmetatable(luanet, metatable)
-- Preload the mscorlib assembly
luanet.load_assembly('mscorlib')";
static string clr_package = @"---
--- This lua module provides auto importing of .net classes into a named package.
--- Makes for super easy use of LuaInterface glue
---
--- example:
--- Threading = CLRPackage(""System"", ""System.Threading"")
--- Threading.Thread.Sleep(100)
---
--- Extensions:
--- import() is a version of CLRPackage() which puts the package into a list which is used by a global __index lookup,
--- and thus works rather like C#'s using statement. It also recognizes the case where one is importing a local
--- assembly, which must end with an explicit .dll extension.
--- Alternatively, luanet.namespace can be used for convenience without polluting the global namespace:
--- local sys,sysi = luanet.namespace {'System','System.IO'}
-- sys.Console.WriteLine(""we are at {0}"",sysi.Directory.GetCurrentDirectory())
-- LuaInterface hosted with stock Lua interpreter will need to explicitly require this...
if not luanet then require 'luanet' end
local import_type, load_assembly = luanet.import_type, luanet.load_assembly
local mt = {
--- Lookup a previously unfound class and add it to our table
__index = function(package, classname)
local class = rawget(package, classname)
if class == nil then
class = import_type(package.packageName .. ""."" .. classname)
if class == nil then class = import_type(classname) end
package[classname] = class -- keep what we found around, so it will be shared
end
return class
end
}
function luanet.namespace(ns)
if type(ns) == 'table' then
local res = {}
for i = 1,#ns do
res[i] = luanet.namespace(ns[i])
end
return unpack(res)
end
-- FIXME - table.packageName could instead be a private index (see Lua 13.4.4)
local t = { packageName = ns }
setmetatable(t,mt)
return t
end
local globalMT, packages
local function set_global_mt()
packages = {}
globalMT = {
__index = function(T,classname)
for i,package in ipairs(packages) do
local class = package[classname]
if class then
_G[classname] = class
return class
end
end
end
}
setmetatable(_G, globalMT)
end
--- Create a new Package class
function CLRPackage(assemblyName, packageName)
-- a sensible default...
packageName = packageName or assemblyName
local ok = pcall(load_assembly,assemblyName) -- Make sure our assembly is loaded
return luanet.namespace(packageName)
end
function import (assemblyName, packageName)
if not globalMT then
set_global_mt()
end
if not packageName then
local i = assemblyName:find('%.dll$')
if i then packageName = assemblyName:sub(1,i-1)
else packageName = assemblyName end
end
local t = CLRPackage(assemblyName,packageName)
table.insert(packages,t)
return t
end
function luanet.make_array (tp,tbl)
local arr = tp[#tbl]
for i,v in ipairs(tbl) do
arr:SetValue(v,i-1)
end
return arr
end
function luanet.each(o)
local e = o:GetEnumerator()
return function()
if e:MoveNext() then
return e.Current
end
end
end
";
public bool UseTraceback { get; set; } = false;
#region Globals auto-complete
/// <summary>
/// An alphabetically sorted list of all globals (objects, methods, etc.) externally added to this Lua instance
/// </summary>
/// <remarks>Members of globals are also listed. The formatting is optimized for text input auto-completion.</remarks>
public IEnumerable<string> Globals {
get {
// Only sort list when necessary
if (!globalsSorted) {
globals.Sort ();
globalsSorted = true;
}
return globals;
}
}
#endregion
public Lua ()
{
luaState = LuaLib.LuaLNewState ();
LuaLib.LuaLOpenLibs (luaState);
Init ();
// We need to keep this in a managed reference so the delegate doesn't get garbage collected
panicCallback = new LuaNativeFunction (PanicCallback);
LuaLib.LuaAtPanic (luaState, panicCallback);
}
/*
* CAUTION: NLua.Lua instances can't share the same lua state!
*/
public Lua (LuaState lState)
{
LuaLib.LuaPushString (lState, "LUAINTERFACE LOADED");
LuaLib.LuaGetTable (lState, (int)LuaIndexes.Registry);
if (LuaLib.LuaToBoolean (lState, -1)) {
LuaLib.LuaSetTop (lState, -2);
throw new LuaException ("There is already a NLua.Lua instance associated with this Lua state");
} else {
luaState = lState;
_StatePassed = true;
LuaLib.LuaSetTop (luaState, -2);
Init ();
}
}
void Init ()
{
LuaLib.LuaPushString (luaState, "LUAINTERFACE LOADED");
LuaLib.LuaPushBoolean (luaState, true);
LuaLib.LuaSetTable (luaState, (int)LuaIndexes.Registry);
if (_StatePassed == false) {
LuaLib.LuaNewTable (luaState);
LuaLib.LuaSetGlobal (luaState, "luanet");
}
LuaLib.LuaNetPushGlobalTable (luaState);
LuaLib.LuaGetGlobal (luaState, "luanet");
LuaLib.LuaPushString (luaState, "getmetatable");
LuaLib.LuaGetGlobal (luaState, "getmetatable");
LuaLib.LuaSetTable (luaState, -3);
LuaLib.LuaNetPopGlobalTable (luaState);
translator = new ObjectTranslator (this, luaState);
lock (translatorPoolLock)
{
ObjectTranslatorPool.Instance.Add (luaState, translator);
}
LuaLib.LuaNetPopGlobalTable (luaState);
LuaLib.LuaLDoString (luaState, Lua.initLuanet);
}
public void Close ()
{
if (_StatePassed)
return;
if (! CheckNull.IsNull(luaState)) {
lock (translatorPoolLock)
{
LuaCore.LuaClose (luaState);
ObjectTranslatorPool.Instance.Remove (luaState);
}
}
}
#if MONOTOUCH
[MonoPInvokeCallback (typeof (LuaNativeFunction))]
#endif
static int PanicCallback (LuaState luaState)
{
string reason = string.Format ("unprotected error in call to Lua API ({0})", LuaLib.LuaToString (luaState, -1));
throw new LuaException (reason);
}
/// <summary>
/// Assuming we have a Lua error string sitting on the stack, throw a C# exception out to the user's app
/// </summary>
/// <exception cref = "LuaScriptException">Thrown if the script caused an exception</exception>
private void ThrowExceptionFromError (int oldTop)
{
object err = translator.GetObject (luaState, -1);
LuaLib.LuaSetTop (luaState, oldTop);
// A pre-wrapped exception - just rethrow it (stack trace of InnerException will be preserved)
var luaEx = err as LuaScriptException;
if (luaEx != null)
throw luaEx;
// A non-wrapped Lua error (best interpreted as a string) - wrap it and throw it
if (err == null)
err = "Unknown Lua Error";
throw new LuaScriptException (err.ToString (), string.Empty);
}
/// <summary>
/// Push a debug.traceback reference onto the stack, for a pcall function to use as error handler. (Remember to increment any top-of-stack markers!)
/// </summary>
private int PushDebugTraceback(LuaState luaState, int argcount)
{
LuaLib.LuaGetGlobal(luaState, "debug");
LuaLib.LuaGetField(luaState, -1, "traceback");
LuaLib.LuaRemove(luaState, -2);
int errindex = -argcount -2;
LuaLib.LuaInsert(luaState, errindex);
return errindex;
}
/// <summary>
/// <para>Return a debug.traceback() call result (a multi-line string, containing a full stack trace, including C calls.</para>
/// <para>Note: it won't return anything unless the interpreter is in the middle of execution - that is, it only makes sense to call it from a method called from Lua, or during a coroutine yield.</para>
/// </summary>
public string GetDebugTraceback()
{
int oldTop = LuaLib.LuaGetTop(luaState);
LuaLib.LuaGetGlobal(luaState, "debug"); // stack: debug
LuaLib.LuaGetField(luaState, -1, "traceback"); // stack: debug,traceback
LuaLib.LuaRemove(luaState, -2); // stack: traceback
LuaLib.LuaPCall(luaState, 0, -1, 0);
return translator.PopValues(luaState, oldTop)[0] as string;
}
/// <summary>
/// Convert C# exceptions into Lua errors
/// </summary>
/// <returns>num of things on stack</returns>
/// <param name = "e">null for no pending exception</param>
internal int SetPendingException (Exception e)
{
var caughtExcept = e;
if (caughtExcept != null) {
translator.ThrowError (luaState, caughtExcept);
LuaLib.LuaPushNil (luaState);
return 1;
} else
return 0;
}
/// <summary>
///
/// </summary>
/// <param name = "chunk"></param>
/// <param name = "name"></param>
/// <returns></returns>
public LuaFunction LoadString (string chunk, string name)
{
int oldTop = LuaLib.LuaGetTop (luaState);
executing = true;
try {
if (LuaLib.LuaLLoadBuffer (luaState, chunk, name) != 0)
ThrowExceptionFromError (oldTop);
} finally {
executing = false;
}
var result = translator.GetFunction (luaState, -1);
translator.PopValues (luaState, oldTop);
return result;
}
/// <summary>
///
/// </summary>
/// <param name = "chunk"></param>
/// <param name = "name"></param>
/// <returns></returns>
public LuaFunction LoadString (byte[] chunk, string name)
{
int oldTop = LuaLib.LuaGetTop (luaState);
executing = true;
try {
if (LuaLib.LuaLLoadBuffer (luaState, chunk, name) != 0)
ThrowExceptionFromError (oldTop);
} finally {
executing = false;
}
var result = translator.GetFunction (luaState, -1);
translator.PopValues (luaState, oldTop);
return result;
}
/// <summary>
/// Load a File on, and return a LuaFunction to execute the file loaded (useful to see if the syntax of a file is ok)
/// </summary>
/// <param name = "fileName"></param>
/// <returns></returns>
public LuaFunction LoadFile (string fileName)
{
int oldTop = LuaLib.LuaGetTop (luaState);
if (LuaLib.LuaLLoadFile (luaState, fileName) != 0)
ThrowExceptionFromError (oldTop);
var result = translator.GetFunction (luaState, -1);
translator.PopValues (luaState, oldTop);
return result;
}
/// <summary>
/// Executes a Lua chunk and returns all the chunk's return values in an array.
/// </summary>
/// <param name = "chunk">Chunk to execute</param>
/// <param name = "chunkName">Name to associate with the chunk. Defaults to "chunk".</param>
/// <returns></returns>
public object[] DoString (byte[] chunk, string chunkName = "chunk")
{
int oldTop = LuaLib.LuaGetTop(luaState);
executing = true;
if (LuaLib.LuaLLoadBuffer(luaState, chunk, chunkName) == 0)
{
int errfunction = 0;
if (UseTraceback) {
errfunction = PushDebugTraceback(luaState, 0);
oldTop++;
}
try
{
if (LuaLib.LuaPCall(luaState, 0, -1, errfunction) == 0)
return translator.PopValues(luaState, oldTop);
else
ThrowExceptionFromError(oldTop);
}
finally
{
executing = false;
}
}
else
ThrowExceptionFromError(oldTop);
return null; // Never reached - keeps compiler happy
}
/// <summary>
/// Executes a Lua chunk and returns all the chunk's return values in an array.
/// </summary>
/// <param name = "chunk">Chunk to execute</param>
/// <param name = "chunkName">Name to associate with the chunk. Defaults to "chunk".</param>
/// <returns></returns>
public object[] DoString (string chunk, string chunkName = "chunk")
{
int oldTop = LuaLib.LuaGetTop(luaState);
executing = true;
if (LuaLib.LuaLLoadBuffer(luaState, chunk, chunkName) == 0)
{
int errfunction = 0;
if (UseTraceback) {
errfunction = PushDebugTraceback(luaState, 0);
oldTop++;
}
try
{
if (LuaLib.LuaPCall(luaState, 0, -1, errfunction) == 0)
return translator.PopValues(luaState, oldTop);
else
ThrowExceptionFromError(oldTop);
}
finally
{
executing = false;
}
}
else
ThrowExceptionFromError(oldTop);
return null; // Never reached - keeps compiler happy
}
/*
* Excutes a Lua file and returns all the chunk's return
* values in an array
*/
public object[] DoFile (string fileName)
{
int oldTop = LuaLib.LuaGetTop (luaState);
if (LuaLib.LuaLLoadFile (luaState, fileName) == 0) {
executing = true;
int errfunction = 0;
if (UseTraceback) {
errfunction = PushDebugTraceback(luaState, 0);
oldTop++;
}
try {
if (LuaLib.LuaPCall(luaState, 0, -1, errfunction) == 0)
return translator.PopValues (luaState, oldTop);
else
ThrowExceptionFromError (oldTop);
} finally {
executing = false;
}
} else
ThrowExceptionFromError (oldTop);
return null; // Never reached - keeps compiler happy
}
/*
* Indexer for global variables from the LuaInterpreter
* Supports navigation of tables by using . operator
*/
public object this [string fullPath] {
get {
object returnValue = null;
int oldTop = LuaLib.LuaGetTop (luaState);
string [] path = FullPathToArray (fullPath);
LuaLib.LuaGetGlobal (luaState, path [0]);
returnValue = translator.GetObject (luaState, -1);
LuaBase dispose = null;
if (path.Length > 1) {
dispose = returnValue as LuaBase;
string[] remainingPath = new string[path.Length - 1];
Array.Copy (path, 1, remainingPath, 0, path.Length - 1);
returnValue = GetObject (remainingPath);
if (dispose != null)
dispose.Dispose ();
}
LuaLib.LuaSetTop (luaState, oldTop);
return returnValue;
}
set {
int oldTop = LuaLib.LuaGetTop (luaState);
string [] path = FullPathToArray (fullPath);
if (path.Length == 1) {
translator.Push (luaState, value);
LuaLib.LuaSetGlobal (luaState, fullPath);
} else {
LuaLib.LuaGetGlobal (luaState, path [0]);
string[] remainingPath = new string[path.Length - 1];
Array.Copy (path, 1, remainingPath, 0, path.Length - 1);
SetObject (remainingPath, value);
}
LuaLib.LuaSetTop (luaState, oldTop);
// Globals auto-complete
if (value == null) {
// Remove now obsolete entries
globals.Remove (fullPath);
} else {
// Add new entries
if (!globals.Contains (fullPath))
RegisterGlobal (fullPath, value.GetType (), 0);
}
}
}
#region Globals auto-complete
/// <summary>
/// Adds an entry to <see cref = "globals"/> (recursivley handles 2 levels of members)
/// </summary>
/// <param name = "path">The index accessor path ot the entry</param>
/// <param name = "type">The type of the entry</param>
/// <param name = "recursionCounter">How deep have we gone with recursion?</param>
private void RegisterGlobal (string path, Type type, int recursionCounter)
{
// If the type is a global method, list it directly
if (type == typeof(LuaNativeFunction)) {
// Format for easy method invocation
globals.Add (path + "(");
}
// 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) {
#region Methods
foreach (var method in type.GetMethods(BindingFlags.Public | BindingFlags.Instance)) {
string name = method.Name;
if (
// Check that the LuaHideAttribute and LuaGlobalAttribute were not applied
(!method.GetCustomAttributes (typeof(LuaHideAttribute), false).Any ()) &&
(!method.GetCustomAttributes (typeof(LuaGlobalAttribute), false).Any ()) &&
// Exclude some generic .NET methods that wouldn't be very usefull in Lua
name != "GetType" && name != "GetHashCode" && name != "Equals" &&
name != "ToString" && name != "Clone" && name != "Dispose" &&
name != "GetEnumerator" && name != "CopyTo" &&
!name.StartsWith ("get_", StringComparison.Ordinal) &&
!name.StartsWith ("set_", StringComparison.Ordinal) &&
!name.StartsWith ("add_", StringComparison.Ordinal) &&
!name.StartsWith ("remove_", StringComparison.Ordinal)) {
// Format for easy method invocation
string command = path + ":" + name + "(";
if (method.GetParameters ().Length == 0)
command += ")";
globals.Add (command);
}
}
#endregion
#region Fields
foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.Instance)) {
if (
// Check that the LuaHideAttribute and LuaGlobalAttribute were not applied
(!field.GetCustomAttributes (typeof(LuaHideAttribute), false).Any ()) &&
(!field.GetCustomAttributes (typeof(LuaGlobalAttribute), false).Any ())) {
// Go into recursion for members
RegisterGlobal (path + "." + field.Name, field.FieldType, recursionCounter + 1);
}
}
#endregion
#region Properties
foreach (var property in type.GetProperties (BindingFlags.Public | BindingFlags.Instance)) {
if (
// Check that the LuaHideAttribute and LuaGlobalAttribute were not applied
(!property.GetCustomAttributes (typeof(LuaHideAttribute), false).Any ()) &&
(!property.GetCustomAttributes (typeof(LuaGlobalAttribute), false).Any ())
// Exclude some generic .NET properties that wouldn't be very useful in Lua
&& property.Name != "Item") {
// Go into recursion for members
RegisterGlobal (path + "." + property.Name, property.PropertyType, recursionCounter + 1);
}
}
#endregion
} else
globals.Add (path); // Otherwise simply add the element to the list
// List will need to be sorted on next access
globalsSorted = false;
}
#endregion
/*
* Navigates a table in the top of the stack, returning
* the value of the specified field
*/
object GetObject (string[] remainingPath)
{
object returnValue = null;
for (int i = 0; i < remainingPath.Length; i++) {
LuaLib.LuaPushString (luaState, remainingPath [i]);
LuaLib.LuaGetTable (luaState, -2);
returnValue = translator.GetObject (luaState, -1);
if (returnValue == null)
break;
}
return returnValue;
}
/*
* Gets a numeric global variable
*/
public double GetNumber (string fullPath)
{
return (double)this [fullPath];
}
/*
* Gets a string global variable
*/
public string GetString (string fullPath)
{
return this [fullPath].ToString ();
}
/*
* Gets a table global variable
*/
public LuaTable GetTable (string fullPath)
{
return (LuaTable)this [fullPath];
}
/*
* Gets a table global variable as an object implementing
* the interfaceType interface
*/
public object GetTable (Type interfaceType, string fullPath)
{
return CodeGeneration.Instance.GetClassInstance (interfaceType, GetTable (fullPath));
}
/*
* Gets a function global variable
*/
public LuaFunction GetFunction (string fullPath)
{
object obj = this [fullPath];
return (obj is LuaNativeFunction ? new LuaFunction ((LuaNativeFunction)obj, this) : (LuaFunction)obj);
}
/*
* Register a delegate type to be used to convert Lua functions to C# delegates (useful for iOS where there is no dynamic code generation)
* type delegateType
*/
public void RegisterLuaDelegateType (Type delegateType, Type luaDelegateType)
{
CodeGeneration.Instance.RegisterLuaDelegateType (delegateType, luaDelegateType);
}
public void RegisterLuaClassType (Type klass, Type luaClass)
{
CodeGeneration.Instance.RegisterLuaClassType (klass, luaClass);
}
public void LoadCLRPackage ()
{
LuaLib.LuaLDoString (luaState, Lua.clr_package);
}
/*
* Gets a function global variable as a delegate of
* type delegateType
*/
public Delegate GetFunction (Type delegateType, string fullPath)
{
return CodeGeneration.Instance.GetDelegate (delegateType, GetFunction (fullPath));
}
/*
* Calls the object as a function with the provided arguments,
* returning the function's returned values inside an array
*/
internal object[] CallFunction (object function, object[] args)
{
return CallFunction (function, args, null);
}
/*
* Calls the object as a function with the provided arguments and
* casting returned values to the types in returnTypes before returning
* them in an array
*/
internal object[] CallFunction (object function, object[] args, Type[] returnTypes)
{
int nArgs = 0;
int oldTop = LuaLib.LuaGetTop (luaState);
if (!LuaLib.LuaCheckStack (luaState, args.Length + 6))
throw new LuaException ("Lua stack overflow");
translator.Push (luaState, function);
if (args != null) {
nArgs = args.Length;
for (int i = 0; i < args.Length; i++)
translator.Push (luaState, args [i]);
}
executing = true;
try {
int errfunction = 0;
if (UseTraceback) {
errfunction = PushDebugTraceback(luaState, nArgs);
oldTop++;
}
int error = LuaLib.LuaPCall (luaState, nArgs, -1, errfunction);
if (error != 0)
ThrowExceptionFromError (oldTop);
} finally {
executing = false;
}
return returnTypes != null ? translator.PopValues (luaState, oldTop, returnTypes) : translator.PopValues (luaState, oldTop);
}
/*
* Navigates a table to set the value of one of its fields
*/
void SetObject (string[] remainingPath, object val)
{
for (int i = 0; i < remainingPath.Length-1; i++) {
LuaLib.LuaPushString (luaState, remainingPath [i]);
LuaLib.LuaGetTable (luaState, -2);
}
LuaLib.LuaPushString (luaState, remainingPath [remainingPath.Length - 1]);
translator.Push (luaState, val);
LuaLib.LuaSetTable (luaState, -3);
}
string [] FullPathToArray (string fullPath)
{
return fullPath.SplitWithEscape ('.', '\\').ToArray ();
}
/*
* Creates a new table as a global variable or as a field
* inside an existing table
*/
public void NewTable (string fullPath)
{
string [] path = FullPathToArray (fullPath);
int oldTop = LuaLib.LuaGetTop (luaState);
if (path.Length == 1) {
LuaLib.LuaNewTable (luaState);
LuaLib.LuaSetGlobal (luaState, fullPath);
} else {
LuaLib.LuaGetGlobal (luaState, path [0]);
for (int i = 1; i < path.Length-1; i++) {
LuaLib.LuaPushString (luaState, path [i]);
LuaLib.LuaGetTable (luaState, -2);
}
LuaLib.LuaPushString (luaState, path [path.Length - 1]);
LuaLib.LuaNewTable (luaState);
LuaLib.LuaSetTable (luaState, -3);
}
LuaLib.LuaSetTop (luaState, oldTop);
}
public Dictionary<object, object> GetTableDict (LuaTable table)
{
var dict = new Dictionary<object, object> ();
int oldTop = LuaLib.LuaGetTop (luaState);
translator.Push (luaState, table);
LuaLib.LuaPushNil (luaState);
while (LuaLib.LuaNext(luaState, -2) != 0) {
dict [translator.GetObject (luaState, -2)] = translator.GetObject (luaState, -1);
LuaLib.LuaSetTop (luaState, -2);
}
LuaLib.LuaSetTop (luaState, oldTop);
return dict;
}
/*
* Lets go of a previously allocated reference to a table, function
* or userdata
*/
#region lua debug functions
/// <summary>
/// Activates the debug hook
/// </summary>
/// <param name = "mask">Mask</param>
/// <param name = "count">Count</param>
/// <returns>see lua docs. -1 if hook is already set</returns>
public int SetDebugHook (EventMasks mask, int count)
{
if (hookCallback == null) {
hookCallback = new LuaHook (Lua.DebugHookCallback);
return LuaCore.LuaSetHook (luaState, hookCallback, (int)mask, count);
}
return -1;
}
/// <summary>
/// Removes the debug hook
/// </summary>
/// <returns>see lua docs</returns>
public int RemoveDebugHook ()
{
hookCallback = null;
return LuaCore.LuaSetHook (luaState, null, 0, 0);
}
/// <summary>
/// Gets the hook mask.
/// </summary>
/// <returns>hook mask</returns>
public EventMasks GetHookMask ()
{
return (EventMasks)LuaCore.LuaGetHookMask (luaState);
}
/// <summary>
/// Gets the hook count
/// </summary>
/// <returns>see lua docs</returns>
public int GetHookCount ()
{
return LuaCore.LuaGetHookCount (luaState);
}
/// <summary>
/// Gets local (see lua docs)
/// </summary>
/// <param name = "luaDebug">lua debug structure</param>
/// <param name = "n">see lua docs</param>
/// <returns>see lua docs</returns>
public string GetLocal (LuaDebug luaDebug, int n)
{
return LuaCore.LuaGetLocal (luaState, luaDebug, n).ToString ();
}
/// <summary>
/// Sets local (see lua docs)
/// </summary>
/// <param name = "luaDebug">lua debug structure</param>
/// <param name = "n">see lua docs</param>
/// <returns>see lua docs</returns>
public string SetLocal (LuaDebug luaDebug, int n)
{
return LuaCore.LuaSetLocal (luaState, luaDebug, n).ToString ();
}
public int GetStack (int level, ref LuaDebug ar)
{
return LuaCore.LuaGetStack (luaState, level,ref ar);
}
public int GetInfo (string what, ref LuaDebug ar)
{
return LuaCore.LuaGetInfo (luaState, what, ref ar);
}
/// <summary>
/// Gets up value (see lua docs)
/// </summary>
/// <param name = "funcindex">see lua docs</param>
/// <param name = "n">see lua docs</param>
/// <returns>see lua docs</returns>
public string GetUpValue (int funcindex, int n)
{
return LuaCore.LuaGetUpValue (luaState, funcindex, n).ToString ();
}
/// <summary>
/// Sets up value (see lua docs)
/// </summary>
/// <param name = "funcindex">see lua docs</param>
/// <param name = "n">see lua docs</param>
/// <returns>see lua docs</returns>
public string SetUpValue (int funcindex, int n)
{
return LuaCore.LuaSetUpValue (luaState, funcindex, n).ToString ();
}
/// <summary>
/// Delegate that is called on lua hook callback
/// </summary>
/// <param name = "luaState">lua state</param>
/// <param name = "luaDebug">Pointer to LuaDebug (lua_debug) structure</param>
///
#if MONOTOUCH
[MonoPInvokeCallback (typeof (LuaHook))]
#endif
#if USE_KOPILUA
static void DebugHookCallback (LuaState luaState, LuaDebug debug)
{
#elif NETFX_CORE
static void DebugHookCallback (LuaState luaState, long luaDebug)
{
IntPtr ptr = new IntPtr (luaDebug);
LuaDebug debug = System.Runtime.InteropServices.Marshal.PtrToStructure <LuaDebug> (ptr);
#else
static void DebugHookCallback (LuaState luaState, IntPtr luaDebug)
{
LuaDebug debug = (LuaDebug)System.Runtime.InteropServices.Marshal.PtrToStructure (luaDebug, typeof (LuaDebug));
#endif
ObjectTranslator translator = ObjectTranslatorPool.Instance.Find (luaState);
Lua lua = translator.Interpreter;
lua.DebugHookCallbackInternal (luaState, debug);
}
private void DebugHookCallbackInternal (LuaState luaState, LuaDebug luaDebug)
{
try {
var temp = DebugHook;
if (temp != null)
temp (this, new DebugHookEventArgs (luaDebug));
} catch (Exception ex) {
OnHookException (new HookExceptionEventArgs (ex));
}
}
private void OnHookException (HookExceptionEventArgs e)
{
var temp = HookException;
if (temp != null)
temp (this, e);
}
/// <summary>
/// Pops a value from the lua stack.
/// </summary>
/// <returns>Returns the top value from the lua stack.</returns>
public object Pop ()
{
int top = LuaLib.LuaGetTop (luaState);
return translator.PopValues (luaState, top - 1) [0];
}
/// <summary>
/// Pushes a value onto the lua stack.
/// </summary>
/// <param name = "value">Value to push.</param>
public void Push (object value)
{
translator.Push (luaState, value);
}
#endregion
internal void DisposeInternal (int reference)
{
if (! CheckNull.IsNull(luaState)) //Fix submitted by Qingrui Li
LuaLib.LuaUnref (luaState, reference);
}
/*
* Gets a field of the table corresponding to the provided reference
* using rawget (do not use metatables)
*/
internal object RawGetObject (int reference, string field)
{
int oldTop = LuaLib.LuaGetTop (luaState);
LuaLib.LuaGetRef (luaState, reference);
LuaLib.LuaPushString (luaState, field);
LuaLib.LuaRawGet (luaState, -2);
object obj = translator.GetObject (luaState, -1);
LuaLib.LuaSetTop (luaState, oldTop);
return obj;
}
/*
* Gets a field of the table or userdata corresponding to the provided reference
*/
internal object GetObject (int reference, string field)
{
int oldTop = LuaLib.LuaGetTop (luaState);
LuaLib.LuaGetRef (luaState, reference);
object returnValue = GetObject (FullPathToArray (field));
LuaLib.LuaSetTop (luaState, oldTop);
return returnValue;
}
/*
* Gets a numeric field of the table or userdata corresponding the the provided reference
*/
internal object GetObject (int reference, object field)
{
int oldTop = LuaLib.LuaGetTop (luaState);
LuaLib.LuaGetRef (luaState, reference);
translator.Push (luaState, field);
LuaLib.LuaGetTable (luaState, -2);
object returnValue = translator.GetObject (luaState, -1);
LuaLib.LuaSetTop (luaState, oldTop);
return returnValue;
}
/*
* 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)
{
int oldTop = LuaLib.LuaGetTop (luaState);
LuaLib.LuaGetRef (luaState, reference);
SetObject (FullPathToArray (field), val);
LuaLib.LuaSetTop (luaState, oldTop);
}
/*
* Sets a numeric field of the table or userdata corresponding the the provided reference
* to the provided value
*/
internal void SetObject (int reference, object field, object val)
{
int oldTop = LuaLib.LuaGetTop (luaState);
LuaLib.LuaGetRef (luaState, reference);
translator.Push (luaState, field);
translator.Push (luaState, val);
LuaLib.LuaSetTable (luaState, -3);
LuaLib.LuaSetTop (luaState, oldTop);
}
public LuaFunction RegisterFunction (string path,MethodBase function /*MethodInfo function*/)
{
return RegisterFunction (path, null, function);
}
/*
* Registers an object's method as a Lua function (global or table field)
* The method may have any signature
*/
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)
{
// We leave nothing on the stack when we are done
int oldTop = LuaLib.LuaGetTop (luaState);
var wrapper = new LuaMethodWrapper (translator, target, new ProxyType(function.DeclaringType), function);
translator.Push (luaState, new LuaNativeFunction (wrapper.invokeFunction));
this [path] = translator.GetObject (luaState, -1);
var f = GetFunction (path);
LuaLib.LuaSetTop (luaState, oldTop);
return f;
}
/*
* Compares the two values referenced by ref1 and ref2 for equality
*/
internal bool CompareRef (int ref1, int ref2)
{
int top = LuaLib.LuaGetTop (luaState);
LuaLib.LuaGetRef (luaState, ref1);
LuaLib.LuaGetRef (luaState, ref2);
int equal = LuaLib.LuaEqual (luaState, -1, -2);
LuaLib.LuaSetTop (luaState, top);
return (equal != 0);
}
internal void PushCSFunction (LuaNativeFunction function)
{
translator.PushFunction (luaState, function);
}
#region IDisposable Members
public virtual void Dispose ()
{
if (translator != null) {
translator.pendingEvents.Dispose ();
translator = null;
}
Close ();
GC.WaitForPendingFinalizers ();
}
#endregion
}
}
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