add lua dll
parent
78a6904ab0
commit
6683f9f5eb
Binary file not shown.
|
@ -30,6 +30,10 @@
|
||||||
<Reference name="OpenSim.Services.Interfaces" path="../../../bin"/>
|
<Reference name="OpenSim.Services.Interfaces" path="../../../bin"/>
|
||||||
<Reference name="OpenSim.Server.Base" path="../../../bin"/>
|
<Reference name="OpenSim.Server.Base" path="../../../bin"/>
|
||||||
<Reference name="OpenSim.Data" path="../../../bin"/>
|
<Reference name="OpenSim.Data" path="../../../bin"/>
|
||||||
|
|
||||||
|
<Reference name="KeraLua.dll" path="../" localCopy="true"/>
|
||||||
|
<Reference name="lua54.dll" path="../" localCopy="true"/>
|
||||||
|
<Reference name="NLua.dll" path="../" localCopy="true"/>
|
||||||
<Files>
|
<Files>
|
||||||
<Match pattern="*.cs" recurse="true"/>
|
<Match pattern="*.cs" recurse="true"/>
|
||||||
</Files>
|
</Files>
|
||||||
|
|
|
@ -1,406 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using KeraLua;
|
|
||||||
using NLua.Method;
|
|
||||||
using NLua.Extensions;
|
|
||||||
|
|
||||||
namespace NLua
|
|
||||||
{
|
|
||||||
using LuaState = KeraLua.Lua;
|
|
||||||
sealed class CheckType
|
|
||||||
{
|
|
||||||
readonly Dictionary<Type, ExtractValue> _extractValues = new Dictionary<Type, ExtractValue>();
|
|
||||||
readonly ExtractValue _extractNetObject;
|
|
||||||
readonly ObjectTranslator _translator;
|
|
||||||
|
|
||||||
public CheckType(ObjectTranslator translator)
|
|
||||||
{
|
|
||||||
_translator = translator;
|
|
||||||
_extractValues.Add(typeof(object), GetAsObject);
|
|
||||||
_extractValues.Add(typeof(sbyte), GetAsSbyte);
|
|
||||||
_extractValues.Add(typeof(byte), GetAsByte);
|
|
||||||
_extractValues.Add(typeof(short), GetAsShort);
|
|
||||||
_extractValues.Add(typeof(ushort), GetAsUshort);
|
|
||||||
_extractValues.Add(typeof(int), GetAsInt);
|
|
||||||
_extractValues.Add(typeof(uint), GetAsUint);
|
|
||||||
_extractValues.Add(typeof(long), GetAsLong);
|
|
||||||
_extractValues.Add(typeof(ulong), GetAsUlong);
|
|
||||||
_extractValues.Add(typeof(double), GetAsDouble);
|
|
||||||
_extractValues.Add(typeof(char), GetAsChar);
|
|
||||||
_extractValues.Add(typeof(float), GetAsFloat);
|
|
||||||
_extractValues.Add(typeof(decimal), GetAsDecimal);
|
|
||||||
_extractValues.Add(typeof(bool), GetAsBoolean);
|
|
||||||
_extractValues.Add(typeof(string), GetAsString);
|
|
||||||
_extractValues.Add(typeof(char[]), GetAsCharArray);
|
|
||||||
_extractValues.Add(typeof(byte[]), GetAsByteArray);
|
|
||||||
_extractValues.Add(typeof(LuaFunction), GetAsFunction);
|
|
||||||
_extractValues.Add(typeof(LuaTable), GetAsTable);
|
|
||||||
_extractValues.Add(typeof(LuaUserData), GetAsUserdata);
|
|
||||||
_extractNetObject = 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();
|
|
||||||
|
|
||||||
return _extractValues.ContainsKey(paramType) ? _extractValues[paramType] : _extractNetObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal ExtractValue CheckLuaType(LuaState luaState, int stackPos, Type paramType)
|
|
||||||
{
|
|
||||||
LuaType luatype = luaState.Type(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
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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 == LuaType.Nil)
|
|
||||||
{
|
|
||||||
// Return the correct extractor anyways
|
|
||||||
if (netParamIsNumeric || paramType == typeof(bool))
|
|
||||||
return _extractValues[paramType];
|
|
||||||
return _extractNetObject;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (paramType == typeof(object))
|
|
||||||
return _extractValues[paramType];
|
|
||||||
|
|
||||||
//CP: Added support for generic parameters
|
|
||||||
if (paramType.IsGenericParameter)
|
|
||||||
{
|
|
||||||
if (luatype == LuaType.Boolean)
|
|
||||||
return _extractValues[typeof(bool)];
|
|
||||||
if (luatype == LuaType.String)
|
|
||||||
return _extractValues[typeof(string)];
|
|
||||||
if (luatype == LuaType.Table)
|
|
||||||
return _extractValues[typeof(LuaTable)];
|
|
||||||
if (luatype == LuaType.UserData)
|
|
||||||
return _extractValues[typeof(object)];
|
|
||||||
if (luatype == LuaType.Function)
|
|
||||||
return _extractValues[typeof(LuaFunction)];
|
|
||||||
if (luatype == LuaType.Number)
|
|
||||||
return _extractValues[typeof(double)];
|
|
||||||
}
|
|
||||||
bool netParamIsString = paramType == typeof(string) || paramType == typeof(char[]) || paramType == typeof(byte[]);
|
|
||||||
|
|
||||||
if (netParamIsNumeric)
|
|
||||||
{
|
|
||||||
if (luaState.IsNumber(stackPos) && !netParamIsString)
|
|
||||||
return _extractValues[paramType];
|
|
||||||
}
|
|
||||||
else if (paramType == typeof(bool))
|
|
||||||
{
|
|
||||||
if (luaState.IsBoolean(stackPos))
|
|
||||||
return _extractValues[paramType];
|
|
||||||
}
|
|
||||||
else if (netParamIsString)
|
|
||||||
{
|
|
||||||
if (luaState.IsString(stackPos))
|
|
||||||
return _extractValues[paramType];
|
|
||||||
if (luatype == LuaType.Nil)
|
|
||||||
return _extractNetObject; // kevinh - silently convert nil to a null string pointer
|
|
||||||
}
|
|
||||||
else if (paramType == typeof(LuaTable))
|
|
||||||
{
|
|
||||||
if (luatype == LuaType.Table || luatype == LuaType.Nil)
|
|
||||||
return _extractValues[paramType];
|
|
||||||
}
|
|
||||||
else if (paramType == typeof(LuaUserData))
|
|
||||||
{
|
|
||||||
if (luatype == LuaType.UserData || luatype == LuaType.Nil)
|
|
||||||
return _extractValues[paramType];
|
|
||||||
}
|
|
||||||
else if (paramType == typeof(LuaFunction))
|
|
||||||
{
|
|
||||||
if (luatype == LuaType.Function || luatype == LuaType.Nil)
|
|
||||||
return _extractValues[paramType];
|
|
||||||
}
|
|
||||||
else if (typeof(Delegate).IsAssignableFrom(paramType) && luatype == LuaType.Function && paramType.GetMethod("Invoke") != null)
|
|
||||||
return new DelegateGenerator(_translator, paramType).ExtractGenerated;
|
|
||||||
else if (paramType.IsInterface && luatype == LuaType.Table)
|
|
||||||
return new ClassGenerator(_translator, paramType).ExtractGenerated;
|
|
||||||
else if ((paramType.IsInterface || paramType.IsClass) && luatype == LuaType.Nil)
|
|
||||||
{
|
|
||||||
// kevinh - allow nil to be silently converted to null - extractNetObject will return null when the item ain't found
|
|
||||||
return _extractNetObject;
|
|
||||||
}
|
|
||||||
else if (luaState.Type(stackPos) == LuaType.Table)
|
|
||||||
{
|
|
||||||
if (luaState.GetMetaField(stackPos, "__index") != LuaType.Nil)
|
|
||||||
{
|
|
||||||
object obj = _translator.GetNetObject(luaState, -1);
|
|
||||||
luaState.SetTop(-2);
|
|
||||||
if (obj != null && paramType.IsInstanceOfType(obj))
|
|
||||||
return _extractNetObject;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
object obj = _translator.GetNetObject(luaState, stackPos);
|
|
||||||
if (obj != null && paramType.IsInstanceOfType(obj))
|
|
||||||
return _extractNetObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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)
|
|
||||||
{
|
|
||||||
if (!luaState.IsNumericType(stackPos))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (luaState.IsInteger(stackPos))
|
|
||||||
return (sbyte)luaState.ToInteger(stackPos);
|
|
||||||
|
|
||||||
return (sbyte)luaState.ToNumber(stackPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
private object GetAsByte(LuaState luaState, int stackPos)
|
|
||||||
{
|
|
||||||
if (!luaState.IsNumericType(stackPos))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (luaState.IsInteger(stackPos))
|
|
||||||
return (byte)luaState.ToInteger(stackPos);
|
|
||||||
|
|
||||||
return (byte)luaState.ToNumber(stackPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
private object GetAsShort(LuaState luaState, int stackPos)
|
|
||||||
{
|
|
||||||
if (!luaState.IsNumericType(stackPos))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (luaState.IsInteger(stackPos))
|
|
||||||
return (short)luaState.ToInteger(stackPos);
|
|
||||||
|
|
||||||
return (short)luaState.ToNumber(stackPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
private object GetAsUshort(LuaState luaState, int stackPos)
|
|
||||||
{
|
|
||||||
if (!luaState.IsNumericType(stackPos))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (luaState.IsInteger(stackPos))
|
|
||||||
return (ushort)luaState.ToInteger(stackPos);
|
|
||||||
|
|
||||||
return (ushort)luaState.ToNumber(stackPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
private object GetAsInt(LuaState luaState, int stackPos)
|
|
||||||
{
|
|
||||||
if (!luaState.IsNumericType(stackPos))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (luaState.IsInteger(stackPos))
|
|
||||||
return (int)luaState.ToInteger(stackPos);
|
|
||||||
|
|
||||||
return (int)luaState.ToNumber(stackPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
private object GetAsUint(LuaState luaState, int stackPos)
|
|
||||||
{
|
|
||||||
if (!luaState.IsNumericType(stackPos))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (luaState.IsInteger(stackPos))
|
|
||||||
return (uint)luaState.ToInteger(stackPos);
|
|
||||||
|
|
||||||
return (uint)luaState.ToNumber(stackPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
private object GetAsLong(LuaState luaState, int stackPos)
|
|
||||||
{
|
|
||||||
if (!luaState.IsNumericType(stackPos))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (luaState.IsInteger(stackPos))
|
|
||||||
return luaState.ToInteger(stackPos);
|
|
||||||
|
|
||||||
return (long)luaState.ToNumber(stackPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
private object GetAsUlong(LuaState luaState, int stackPos)
|
|
||||||
{
|
|
||||||
if (!luaState.IsNumericType(stackPos))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (luaState.IsInteger(stackPos))
|
|
||||||
return (ulong)luaState.ToInteger(stackPos);
|
|
||||||
|
|
||||||
return (ulong)luaState.ToNumber(stackPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
private object GetAsDouble(LuaState luaState, int stackPos)
|
|
||||||
{
|
|
||||||
if (!luaState.IsNumericType(stackPos))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (luaState.IsInteger(stackPos))
|
|
||||||
return (double)luaState.ToInteger(stackPos);
|
|
||||||
|
|
||||||
return luaState.ToNumber(stackPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
private object GetAsChar(LuaState luaState, int stackPos)
|
|
||||||
{
|
|
||||||
if (!luaState.IsNumericType(stackPos))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (luaState.IsInteger(stackPos))
|
|
||||||
return (char)luaState.ToInteger(stackPos);
|
|
||||||
|
|
||||||
return (char)luaState.ToNumber(stackPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
private object GetAsFloat(LuaState luaState, int stackPos)
|
|
||||||
{
|
|
||||||
if (!luaState.IsNumericType(stackPos))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (luaState.IsInteger(stackPos))
|
|
||||||
return (float)luaState.ToInteger(stackPos);
|
|
||||||
|
|
||||||
return (float)luaState.ToNumber(stackPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
private object GetAsDecimal(LuaState luaState, int stackPos)
|
|
||||||
{
|
|
||||||
if (!luaState.IsNumericType(stackPos))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (luaState.IsInteger(stackPos))
|
|
||||||
return (decimal)luaState.ToInteger(stackPos);
|
|
||||||
|
|
||||||
return (decimal)luaState.ToNumber(stackPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
private object GetAsBoolean(LuaState luaState, int stackPos)
|
|
||||||
{
|
|
||||||
return luaState.ToBoolean(stackPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
private object GetAsCharArray(LuaState luaState, int stackPos)
|
|
||||||
{
|
|
||||||
if (!luaState.IsString(stackPos))
|
|
||||||
return null;
|
|
||||||
string retVal = luaState.ToString(stackPos, false);
|
|
||||||
return retVal.ToCharArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
private object GetAsByteArray(LuaState luaState, int stackPos)
|
|
||||||
{
|
|
||||||
if (!luaState.IsString(stackPos))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
byte [] retVal = luaState.ToBuffer(stackPos, false);
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
private object GetAsString(LuaState luaState, int stackPos)
|
|
||||||
{
|
|
||||||
if (!luaState.IsString(stackPos))
|
|
||||||
return null;
|
|
||||||
return luaState.ToString(stackPos, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 (luaState.Type(stackPos) == LuaType.Table)
|
|
||||||
{
|
|
||||||
if (luaState.GetMetaField(stackPos, "__index") != LuaType.Nil)
|
|
||||||
{
|
|
||||||
if (luaState.CheckMetaTable(-1, _translator.Tag))
|
|
||||||
{
|
|
||||||
luaState.Insert(stackPos);
|
|
||||||
luaState.Remove(stackPos + 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
luaState.SetTop(-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 || luaState.Type(stackPos) != LuaType.Table)
|
|
||||||
return obj;
|
|
||||||
|
|
||||||
if (luaState.GetMetaField(stackPos, "__index") == LuaType.Nil)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (luaState.CheckMetaTable(-1, _translator.Tag))
|
|
||||||
{
|
|
||||||
luaState.Insert(stackPos);
|
|
||||||
luaState.Remove(stackPos + 1);
|
|
||||||
obj = _translator.GetNetObject(luaState, stackPos);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
luaState.SetTop(-2);
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
using System;
|
|
||||||
using KeraLua;
|
|
||||||
|
|
||||||
namespace NLua.Event
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Event args for hook callback event
|
|
||||||
/// </summary>
|
|
||||||
public class DebugHookEventArgs : EventArgs
|
|
||||||
{
|
|
||||||
public DebugHookEventArgs(LuaDebug luaDebug)
|
|
||||||
{
|
|
||||||
LuaDebug = luaDebug;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Lua Debug Information
|
|
||||||
/// </summary>
|
|
||||||
public LuaDebug LuaDebug { get; }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace NLua.Event
|
|
||||||
{
|
|
||||||
public class HookExceptionEventArgs : EventArgs
|
|
||||||
{
|
|
||||||
public Exception Exception { get; }
|
|
||||||
|
|
||||||
public HookExceptionEventArgs(Exception ex)
|
|
||||||
{
|
|
||||||
Exception = ex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace NLua.Exceptions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Exceptions thrown by the Lua runtime
|
|
||||||
/// </summary>
|
|
||||||
[Serializable]
|
|
||||||
public class LuaException : Exception
|
|
||||||
{
|
|
||||||
public LuaException (string message) : base(message)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public LuaException (string message, Exception innerException) : base(message, innerException)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,52 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace NLua.Exceptions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Exceptions thrown by the Lua runtime because of errors in the script
|
|
||||||
/// </summary>
|
|
||||||
///
|
|
||||||
[Serializable]
|
|
||||||
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 readonly string _source;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The position in the script where the exception was triggered.
|
|
||||||
/// </summary>
|
|
||||||
public override string Source => _source;
|
|
||||||
|
|
||||||
/// <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)
|
|
||||||
{
|
|
||||||
_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)
|
|
||||||
{
|
|
||||||
_source = source;
|
|
||||||
IsNetException = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
// Prepend the error source
|
|
||||||
return GetType().FullName + ": " + _source + Message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,122 +0,0 @@
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using KeraLua;
|
|
||||||
using LuaState=KeraLua.Lua;
|
|
||||||
|
|
||||||
namespace NLua.Extensions
|
|
||||||
{
|
|
||||||
static class LuaExtensions
|
|
||||||
{
|
|
||||||
public static bool CheckMetaTable(this LuaState state, int index, IntPtr tag)
|
|
||||||
{
|
|
||||||
if (!state.GetMetaTable(index))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
state.PushLightUserData(tag);
|
|
||||||
state.RawGet(-2);
|
|
||||||
bool isNotNil = !state.IsNil(-1);
|
|
||||||
state.SetTop(-3);
|
|
||||||
return isNotNil;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void PopGlobalTable(this LuaState luaState)
|
|
||||||
{
|
|
||||||
luaState.RawSetInteger(LuaRegistry.Index, (long) LuaRegistryIndex.Globals);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void GetRef (this LuaState luaState, int reference)
|
|
||||||
{
|
|
||||||
luaState.RawGetInteger(LuaRegistry.Index, reference);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReSharper disable once IdentifierTypo
|
|
||||||
public static void Unref (this LuaState luaState, int reference)
|
|
||||||
{
|
|
||||||
luaState.Unref(LuaRegistry.Index, reference);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool AreEqual(this LuaState luaState, int ref1, int ref2)
|
|
||||||
{
|
|
||||||
return luaState.Compare(ref1, ref2, LuaCompare.Equal);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IntPtr CheckUData(this LuaState state, int ud, string name)
|
|
||||||
{
|
|
||||||
IntPtr p = state.ToUserData(ud);
|
|
||||||
if (p == IntPtr.Zero)
|
|
||||||
return IntPtr.Zero;
|
|
||||||
if (!state.GetMetaTable(ud))
|
|
||||||
return IntPtr.Zero;
|
|
||||||
|
|
||||||
state.GetField(LuaRegistry.Index, name);
|
|
||||||
|
|
||||||
bool isEqual = state.RawEqual(-1, -2);
|
|
||||||
|
|
||||||
state.Pop(2);
|
|
||||||
|
|
||||||
if (isEqual)
|
|
||||||
return p;
|
|
||||||
|
|
||||||
return IntPtr.Zero;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int ToNetObject(this LuaState state, int index, IntPtr tag)
|
|
||||||
{
|
|
||||||
if (state.Type(index) != LuaType.UserData)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
IntPtr userData;
|
|
||||||
|
|
||||||
if (state.CheckMetaTable(index, tag))
|
|
||||||
{
|
|
||||||
userData = state.ToUserData(index);
|
|
||||||
if (userData != IntPtr.Zero)
|
|
||||||
return Marshal.ReadInt32(userData);
|
|
||||||
}
|
|
||||||
|
|
||||||
userData = state.CheckUData(index, "luaNet_class");
|
|
||||||
if (userData != IntPtr.Zero)
|
|
||||||
return Marshal.ReadInt32(userData);
|
|
||||||
|
|
||||||
userData = state.CheckUData(index, "luaNet_searchbase");
|
|
||||||
if (userData != IntPtr.Zero)
|
|
||||||
return Marshal.ReadInt32(userData);
|
|
||||||
|
|
||||||
userData = state.CheckUData(index, "luaNet_function");
|
|
||||||
if (userData != IntPtr.Zero)
|
|
||||||
return Marshal.ReadInt32(userData);
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void NewUData(this LuaState state, int val)
|
|
||||||
{
|
|
||||||
IntPtr pointer = state.NewUserData(Marshal.SizeOf(typeof(int)));
|
|
||||||
Marshal.WriteInt32(pointer, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int RawNetObj(this LuaState state, int index)
|
|
||||||
{
|
|
||||||
IntPtr pointer = state.ToUserData(index);
|
|
||||||
if (pointer == IntPtr.Zero)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return Marshal.ReadInt32(pointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int CheckUObject(this LuaState state, int index, string name)
|
|
||||||
{
|
|
||||||
IntPtr udata = state.CheckUData(index, name);
|
|
||||||
if (udata == IntPtr.Zero)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return Marshal.ReadInt32(udata);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool IsNumericType(this LuaState state, int index)
|
|
||||||
{
|
|
||||||
return state.Type(index) == LuaType.Number;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace NLua.Extensions
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,137 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
namespace NLua.Extensions
|
|
||||||
{
|
|
||||||
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 HasAdditionOperator(this Type t)
|
|
||||||
{
|
|
||||||
if (t.IsPrimitive)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return t.HasMethod("op_Addition");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool HasSubtractionOperator(this Type t)
|
|
||||||
{
|
|
||||||
if (t.IsPrimitive)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return t.HasMethod("op_Subtraction");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool HasMultiplyOperator(this Type t)
|
|
||||||
{
|
|
||||||
if (t.IsPrimitive)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return t.HasMethod("op_Multiply");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool HasDivisionOperator(this Type t)
|
|
||||||
{
|
|
||||||
if (t.IsPrimitive)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return t.HasMethod("op_Division");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool HasModulusOperator(this Type t)
|
|
||||||
{
|
|
||||||
if (t.IsPrimitive)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return t.HasMethod("op_Modulus");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool HasUnaryNegationOperator(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 HasEqualityOperator(this Type t)
|
|
||||||
{
|
|
||||||
if (t.IsPrimitive)
|
|
||||||
return true;
|
|
||||||
return t.HasMethod("op_Equality");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool HasLessThanOperator(this Type t)
|
|
||||||
{
|
|
||||||
if (t.IsPrimitive)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return t.HasMethod("op_LessThan");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool HasLessThanOrEqualOperator(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, string name, IEnumerable<Assembly> assemblies = null)
|
|
||||||
{
|
|
||||||
var types = new List<Type>();
|
|
||||||
|
|
||||||
types.AddRange(type.Assembly.GetTypes().Where(t => t.IsPublic));
|
|
||||||
|
|
||||||
if (assemblies != null)
|
|
||||||
{
|
|
||||||
foreach (Assembly item in assemblies)
|
|
||||||
{
|
|
||||||
if (item == type.Assembly)
|
|
||||||
continue;
|
|
||||||
types.AddRange(item.GetTypes().Where(t => t.IsPublic && t.IsClass && t.IsSealed && t.IsAbstract && !t.IsNested));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var query = types
|
|
||||||
.SelectMany(extensionType => extensionType.GetMethods(name, BindingFlags.Static | BindingFlags.Public),
|
|
||||||
(extensionType, method) => new {extensionType, method})
|
|
||||||
.Where(t => t.method.IsDefined(typeof(ExtensionAttribute), false))
|
|
||||||
.Where(t =>
|
|
||||||
t.method.GetParameters()[0].ParameterType == type ||
|
|
||||||
t.method.GetParameters()[0].ParameterType.IsAssignableFrom(type) ||
|
|
||||||
type.GetInterfaces().Contains(t.method.GetParameters()[0].ParameterType))
|
|
||||||
.Select(t => t.method);
|
|
||||||
|
|
||||||
return query.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Extends the System.Type-type to search for a given extended MethodeName.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="t"></param>
|
|
||||||
/// <param name="name"></param>
|
|
||||||
/// <param name="assemblies"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static MethodInfo GetExtensionMethod(this Type t, string name, IEnumerable<Assembly> assemblies = null)
|
|
||||||
{
|
|
||||||
var mi = t.GetExtensionMethods(name, assemblies).ToArray();
|
|
||||||
if (mi.Length == 0)
|
|
||||||
return null;
|
|
||||||
return mi[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
using System;
|
|
||||||
using LuaState = KeraLua.Lua;
|
|
||||||
|
|
||||||
namespace NLua
|
|
||||||
{
|
|
||||||
class ClassGenerator
|
|
||||||
{
|
|
||||||
private readonly ObjectTranslator _translator;
|
|
||||||
private readonly 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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,752 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
using System.Reflection.Emit;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using NLua.Method;
|
|
||||||
|
|
||||||
namespace NLua
|
|
||||||
{
|
|
||||||
class CodeGeneration
|
|
||||||
{
|
|
||||||
private readonly Dictionary<Type, LuaClassType> _classCollection = new Dictionary<Type, LuaClassType>();
|
|
||||||
private readonly Dictionary<Type, Type> _delegateCollection = new Dictionary<Type, Type>();
|
|
||||||
|
|
||||||
#if !NETSTANDARD && !WINDOWS_UWP
|
|
||||||
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
|
|
||||||
var assemblyName = new AssemblyName();
|
|
||||||
assemblyName.Name = "NLua_generatedcode";
|
|
||||||
// Create a new assembly with one module.
|
|
||||||
#if NETCOREAPP
|
|
||||||
newAssembly = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
|
|
||||||
newModule = newAssembly.DefineDynamicModule("NLua_generatedcode");
|
|
||||||
#elif !NETSTANDARD && !WINDOWS_UWP
|
|
||||||
newAssembly = Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
|
|
||||||
newModule = newAssembly.DefineDynamicModule("NLua_generatedcode");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Singleton instance of the class
|
|
||||||
*/
|
|
||||||
public static CodeGeneration Instance { get; } = new CodeGeneration();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Generates an event handler that calls a Lua function
|
|
||||||
*/
|
|
||||||
private Type GenerateEvent(Type eventHandlerType)
|
|
||||||
{
|
|
||||||
#if NETSTANDARD || WINDOWS_UWP
|
|
||||||
throw new NotImplementedException(" Emit not available on .NET Standard ");
|
|
||||||
#else
|
|
||||||
string typeName;
|
|
||||||
lock (this)
|
|
||||||
{
|
|
||||||
typeName = "LuaGeneratedClass" + luaClassNumber;
|
|
||||||
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 NETSTANDARD || WINDOWS_UWP
|
|
||||||
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;
|
|
||||||
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 NETSTANDARD || WINDOWS_UWP
|
|
||||||
throw new NotImplementedException (" Emit not available on .NET Standard ");
|
|
||||||
#else
|
|
||||||
string typeName;
|
|
||||||
lock (this)
|
|
||||||
{
|
|
||||||
typeName = "LuaGeneratedClass" + luaClassNumber;
|
|
||||||
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 (!paramInfo[i].IsIn && paramInfo[i].IsOut)
|
|
||||||
{
|
|
||||||
nOutParams++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (paramTypes[i].IsByRef)
|
|
||||||
{
|
|
||||||
returnTypesList.Add(paramTypes[i].GetElementType());
|
|
||||||
nOutAndRefParams++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
returnTypes = returnTypesList.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !NETSTANDARD && !WINDOWS_UWP
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 NETSTANDARD || WINDOWS_UWP
|
|
||||||
throw new NotImplementedException (" Emit not available on .NET Standard ");
|
|
||||||
#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)
|
|
||||||
{
|
|
||||||
var 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();
|
|
||||||
return Delegate.CreateDelegate(delegateType, luaDelegate, "CallFunction");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
using System;
|
|
||||||
using LuaState = KeraLua.Lua;
|
|
||||||
|
|
||||||
namespace NLua
|
|
||||||
{
|
|
||||||
class DelegateGenerator
|
|
||||||
{
|
|
||||||
private readonly ObjectTranslator _translator;
|
|
||||||
private readonly 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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
1262
src/LUA/Lua.cs
1262
src/LUA/Lua.cs
File diff suppressed because it is too large
Load Diff
|
@ -1,86 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace NLua
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Base class to provide consistent disposal flow across lua objects. Uses code provided by Yves Duhoux and suggestions by Hans Schmeidenbacher and Qingrui Li
|
|
||||||
/// </summary>
|
|
||||||
public abstract class LuaBase : IDisposable
|
|
||||||
{
|
|
||||||
private bool _disposed;
|
|
||||||
protected readonly int _Reference;
|
|
||||||
Lua _lua;
|
|
||||||
|
|
||||||
protected bool TryGet(out Lua lua)
|
|
||||||
{
|
|
||||||
if (_lua.State == null)
|
|
||||||
{
|
|
||||||
lua = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
lua = _lua;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
protected LuaBase(int reference, Lua lua)
|
|
||||||
{
|
|
||||||
_lua = lua;
|
|
||||||
_Reference = reference;
|
|
||||||
}
|
|
||||||
|
|
||||||
~LuaBase()
|
|
||||||
{
|
|
||||||
Dispose(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Dispose(true);
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DisposeLuaReference(bool finalized)
|
|
||||||
{
|
|
||||||
if (_lua == null)
|
|
||||||
return;
|
|
||||||
Lua lua;
|
|
||||||
if (!TryGet(out lua))
|
|
||||||
return;
|
|
||||||
|
|
||||||
lua.DisposeInternal(_Reference, finalized);
|
|
||||||
}
|
|
||||||
public virtual void Dispose(bool disposeManagedResources)
|
|
||||||
{
|
|
||||||
if (_disposed)
|
|
||||||
return;
|
|
||||||
|
|
||||||
bool finalized = !disposeManagedResources;
|
|
||||||
|
|
||||||
if (_Reference != 0)
|
|
||||||
{
|
|
||||||
DisposeLuaReference(finalized);
|
|
||||||
}
|
|
||||||
|
|
||||||
_lua = null;
|
|
||||||
_disposed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(object o)
|
|
||||||
{
|
|
||||||
var reference = o as LuaBase;
|
|
||||||
if (reference == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Lua lua;
|
|
||||||
if (!TryGet(out lua))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return lua.CompareRef(reference._Reference, _Reference);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
return _Reference;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,91 +0,0 @@
|
||||||
using System;
|
|
||||||
using KeraLua;
|
|
||||||
|
|
||||||
using LuaState = KeraLua.Lua;
|
|
||||||
using LuaNativeFunction = KeraLua.LuaFunction;
|
|
||||||
|
|
||||||
namespace NLua
|
|
||||||
{
|
|
||||||
public class LuaFunction : LuaBase
|
|
||||||
{
|
|
||||||
internal readonly LuaNativeFunction function;
|
|
||||||
|
|
||||||
public LuaFunction(int reference, Lua interpreter):base(reference, interpreter)
|
|
||||||
{
|
|
||||||
function = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LuaFunction(LuaNativeFunction nativeFunction, Lua interpreter):base (0, interpreter)
|
|
||||||
{
|
|
||||||
function = nativeFunction;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Calls the function casting return values to the types
|
|
||||||
* in returnTypes
|
|
||||||
*/
|
|
||||||
internal object[] Call(object[] args, Type[] returnTypes)
|
|
||||||
{
|
|
||||||
Lua lua;
|
|
||||||
if (!TryGet(out lua))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return lua.CallFunction(this, args, returnTypes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Calls the function and returns its return values inside
|
|
||||||
* an array
|
|
||||||
*/
|
|
||||||
public object[] Call(params object[] args)
|
|
||||||
{
|
|
||||||
Lua lua;
|
|
||||||
if (!TryGet(out lua))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return lua.CallFunction(this, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Pushes the function into the Lua stack
|
|
||||||
*/
|
|
||||||
internal void Push(LuaState luaState)
|
|
||||||
{
|
|
||||||
Lua lua;
|
|
||||||
if (!TryGet(out lua))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (_Reference != 0)
|
|
||||||
luaState.RawGetInteger(LuaRegistry.Index, _Reference);
|
|
||||||
else
|
|
||||||
lua.PushCSFunction(function);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return "function";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(object o)
|
|
||||||
{
|
|
||||||
var l = o as LuaFunction;
|
|
||||||
|
|
||||||
if (l == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Lua lua;
|
|
||||||
if (!TryGet(out lua))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (_Reference != 0 && l._Reference != 0)
|
|
||||||
return lua.CompareRef(l._Reference, _Reference);
|
|
||||||
|
|
||||||
return function == l.function;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
return _Reference != 0 ? _Reference : function.GetHashCode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace NLua
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Marks a method for global usage in Lua scripts
|
|
||||||
/// </summary>
|
|
||||||
/// <see cref="LuaRegistrationHelper.TaggedInstanceMethods"/>
|
|
||||||
/// <see cref="LuaRegistrationHelper.TaggedStaticMethods"/>
|
|
||||||
[AttributeUsage(AttributeTargets.Method)]
|
|
||||||
public sealed class LuaGlobalAttribute : Attribute
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// An alternative name to use for calling the function in Lua - leave empty for CLR name
|
|
||||||
/// </summary>
|
|
||||||
public string Name { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A description of the function
|
|
||||||
/// </summary>
|
|
||||||
public string Description { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace NLua
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Marks a method, field or property to be hidden from Lua auto-completion
|
|
||||||
/// </summary>
|
|
||||||
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
|
|
||||||
public sealed class LuaHideAttribute : Attribute
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,98 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
|
|
||||||
namespace NLua
|
|
||||||
{
|
|
||||||
public static class LuaRegistrationHelper
|
|
||||||
{
|
|
||||||
#region Tagged instance methods
|
|
||||||
/// <summary>
|
|
||||||
/// Registers all public instance methods in an object tagged with <see cref="LuaGlobalAttribute"/> as Lua global functions
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="lua">The Lua VM to add the methods to</param>
|
|
||||||
/// <param name="o">The object to get the methods from</param>
|
|
||||||
public static void TaggedInstanceMethods(Lua lua, object o)
|
|
||||||
{
|
|
||||||
#region Sanity checks
|
|
||||||
if (lua == null)
|
|
||||||
throw new ArgumentNullException(nameof(lua));
|
|
||||||
|
|
||||||
if (o == null)
|
|
||||||
throw new ArgumentNullException(nameof(o));
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
foreach (var method in o.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public))
|
|
||||||
{
|
|
||||||
foreach (LuaGlobalAttribute attribute in method.GetCustomAttributes(typeof(LuaGlobalAttribute), true))
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(attribute.Name))
|
|
||||||
lua.RegisterFunction(method.Name, o, method); // CLR name
|
|
||||||
else
|
|
||||||
lua.RegisterFunction(attribute.Name, o, method); // Custom name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Tagged static methods
|
|
||||||
/// <summary>
|
|
||||||
/// Registers all public static methods in a class tagged with <see cref="LuaGlobalAttribute"/> as Lua global functions
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="lua">The Lua VM to add the methods to</param>
|
|
||||||
/// <param name="type">The class type to get the methods from</param>
|
|
||||||
public static void TaggedStaticMethods(Lua lua, Type type)
|
|
||||||
{
|
|
||||||
#region Sanity checks
|
|
||||||
if (lua == null)
|
|
||||||
throw new ArgumentNullException(nameof(lua));
|
|
||||||
|
|
||||||
if (type == null)
|
|
||||||
throw new ArgumentNullException(nameof(type));
|
|
||||||
|
|
||||||
if (!type.IsClass)
|
|
||||||
throw new ArgumentException("The type must be a class!", nameof(type));
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
foreach (var method in type.GetMethods(BindingFlags.Static | BindingFlags.Public))
|
|
||||||
{
|
|
||||||
foreach (LuaGlobalAttribute attribute in method.GetCustomAttributes(typeof(LuaGlobalAttribute), false))
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(attribute.Name))
|
|
||||||
lua.RegisterFunction(method.Name, null, method); // CLR name
|
|
||||||
else
|
|
||||||
lua.RegisterFunction(attribute.Name, null, method); // Custom name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Registers an enumeration's values for usage as a Lua variable table
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T">The enum type to register</typeparam>
|
|
||||||
/// <param name="lua">The Lua VM to add the enum to</param>
|
|
||||||
[SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "The type parameter is used to select an enum type")]
|
|
||||||
public static void Enumeration<T>(Lua lua)
|
|
||||||
{
|
|
||||||
if (lua == null)
|
|
||||||
throw new ArgumentNullException(nameof(lua));
|
|
||||||
|
|
||||||
Type type = typeof(T);
|
|
||||||
|
|
||||||
if (!type.IsEnum)
|
|
||||||
throw new ArgumentException("The type must be an enumeration!");
|
|
||||||
|
|
||||||
|
|
||||||
string[] names = Enum.GetNames(type);
|
|
||||||
var values = (T[])Enum.GetValues(type);
|
|
||||||
lua.NewTable(type.Name);
|
|
||||||
|
|
||||||
for (int i = 0; i < names.Length; i++)
|
|
||||||
{
|
|
||||||
string path = type.Name + "." + names[i];
|
|
||||||
lua.SetObjectToPath(path, values[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,120 +0,0 @@
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
|
|
||||||
using NLua.Extensions;
|
|
||||||
|
|
||||||
using LuaState = KeraLua.Lua;
|
|
||||||
|
|
||||||
namespace NLua
|
|
||||||
{
|
|
||||||
public class LuaTable : LuaBase
|
|
||||||
{
|
|
||||||
public LuaTable(int reference, Lua interpreter): base(reference, interpreter)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Indexer for string fields of the table
|
|
||||||
*/
|
|
||||||
public object this[string field] {
|
|
||||||
get
|
|
||||||
{
|
|
||||||
Lua lua;
|
|
||||||
if (!TryGet(out lua))
|
|
||||||
return null;
|
|
||||||
return lua.GetObject(_Reference, field);
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
Lua lua;
|
|
||||||
if (!TryGet(out lua))
|
|
||||||
return;
|
|
||||||
lua.SetObject(_Reference, field, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Indexer for numeric fields of the table
|
|
||||||
*/
|
|
||||||
public object this[object field] {
|
|
||||||
get
|
|
||||||
{
|
|
||||||
Lua lua;
|
|
||||||
if (!TryGet(out lua))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return lua.GetObject(_Reference, field);
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
Lua lua;
|
|
||||||
if (!TryGet(out lua))
|
|
||||||
return;
|
|
||||||
|
|
||||||
lua.SetObject(_Reference, field, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public IDictionaryEnumerator GetEnumerator()
|
|
||||||
{
|
|
||||||
Lua lua;
|
|
||||||
if (!TryGet(out lua))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return lua.GetTableDict(this).GetEnumerator();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ICollection Keys
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
Lua lua;
|
|
||||||
if (!TryGet(out lua))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return lua.GetTableDict(this).Keys;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public ICollection Values
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
Lua lua;
|
|
||||||
if (!TryGet(out lua))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return lua.GetTableDict(this).Values;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Gets an string fields of a table ignoring its metatable,
|
|
||||||
* if it exists
|
|
||||||
*/
|
|
||||||
internal object RawGet(string field)
|
|
||||||
{
|
|
||||||
Lua lua;
|
|
||||||
if (!TryGet(out lua))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return lua.RawGetObject(_Reference, field);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Pushes this table into the Lua stack
|
|
||||||
*/
|
|
||||||
internal void Push(LuaState luaState)
|
|
||||||
{
|
|
||||||
luaState.GetRef(_Reference);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return "table";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,74 +0,0 @@
|
||||||
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace NLua
|
|
||||||
{
|
|
||||||
public class LuaUserData : LuaBase
|
|
||||||
{
|
|
||||||
public LuaUserData(int reference, Lua interpreter):base(reference, interpreter)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Indexer for string fields of the userdata
|
|
||||||
*/
|
|
||||||
public object this[string field] {
|
|
||||||
get
|
|
||||||
{
|
|
||||||
Lua lua;
|
|
||||||
if (!TryGet(out lua))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return lua.GetObject(_Reference, field);
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
Lua lua;
|
|
||||||
if (!TryGet(out lua))
|
|
||||||
return;
|
|
||||||
|
|
||||||
lua.SetObject(_Reference, field, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Indexer for numeric fields of the userdata
|
|
||||||
*/
|
|
||||||
public object this[object field] {
|
|
||||||
get
|
|
||||||
{
|
|
||||||
Lua lua;
|
|
||||||
if (!TryGet(out lua))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return lua.GetObject(_Reference, field);
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
Lua lua;
|
|
||||||
if (!TryGet(out lua))
|
|
||||||
return;
|
|
||||||
|
|
||||||
lua.SetObject(_Reference, field, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Calls the userdata and returns its return values inside
|
|
||||||
* an array
|
|
||||||
*/
|
|
||||||
public object[] Call(params object[] args)
|
|
||||||
{
|
|
||||||
Lua lua;
|
|
||||||
if (!TryGet(out lua))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return lua.CallFunction(this, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return "userdata";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,36 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace NLua.Method
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// We keep track of what delegates we have auto attached to an event - to allow us to cleanly exit a NLua session
|
|
||||||
/// </summary>
|
|
||||||
class EventHandlerContainer : IDisposable
|
|
||||||
{
|
|
||||||
private readonly Dictionary<Delegate, RegisterEventHandler> _dict = new Dictionary<Delegate, RegisterEventHandler>();
|
|
||||||
|
|
||||||
public void Add(Delegate handler, RegisterEventHandler eventInfo)
|
|
||||||
{
|
|
||||||
_dict.Add(handler, eventInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Remove(Delegate handler)
|
|
||||||
{
|
|
||||||
bool found = _dict.Remove(handler);
|
|
||||||
Debug.Assert(found);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Remove any still registered handlers
|
|
||||||
/// </summary>
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
foreach (KeyValuePair<Delegate, RegisterEventHandler> pair in _dict)
|
|
||||||
pair.Value.RemovePending(pair.Key);
|
|
||||||
|
|
||||||
_dict.Clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,55 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace NLua.Method
|
|
||||||
{
|
|
||||||
public class LuaClassHelper
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Gets the function called name from the provided table,
|
|
||||||
* returning null if it does not exist
|
|
||||||
*/
|
|
||||||
public static LuaFunction GetTableFunction(LuaTable luaTable, string name)
|
|
||||||
{
|
|
||||||
if (luaTable == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
var funcObj = luaTable.RawGet(name) as LuaFunction;
|
|
||||||
|
|
||||||
if (funcObj != null)
|
|
||||||
return funcObj;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Calls the provided function with the provided parameters
|
|
||||||
*/
|
|
||||||
public static object CallFunction(LuaFunction function, object[] args, Type[] returnTypes, object[] inArgs, int[] outArgs)
|
|
||||||
{
|
|
||||||
// args is the return array of arguments, inArgs is the actual array
|
|
||||||
// of arguments passed to the function (with in parameters only), outArgs
|
|
||||||
// has the positions of out parameters
|
|
||||||
object returnValue;
|
|
||||||
int iRefArgs;
|
|
||||||
object[] returnValues = function.Call(inArgs, returnTypes);
|
|
||||||
|
|
||||||
if (returnTypes[0] == typeof(void))
|
|
||||||
{
|
|
||||||
returnValue = null;
|
|
||||||
iRefArgs = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
returnValue = returnValues[0];
|
|
||||||
iRefArgs = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < outArgs.Length; i++)
|
|
||||||
{
|
|
||||||
args[outArgs[i]] = returnValues[iRefArgs];
|
|
||||||
iRefArgs++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace NLua.Method
|
|
||||||
{
|
|
||||||
public class LuaDelegate
|
|
||||||
{
|
|
||||||
public LuaFunction Function;
|
|
||||||
public Type[] ReturnTypes;
|
|
||||||
|
|
||||||
public LuaDelegate()
|
|
||||||
{
|
|
||||||
Function = null;
|
|
||||||
ReturnTypes = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public object CallFunction(object[] args, object[] inArgs, int[] outArgs)
|
|
||||||
{
|
|
||||||
// args is the return array of arguments, inArgs is the actual array
|
|
||||||
// of arguments passed to the function (with in parameters only), outArgs
|
|
||||||
// has the positions of out parameters
|
|
||||||
object returnValue;
|
|
||||||
int iRefArgs;
|
|
||||||
object[] returnValues = Function.Call(inArgs, ReturnTypes);
|
|
||||||
|
|
||||||
if (ReturnTypes[0] == typeof(void))
|
|
||||||
{
|
|
||||||
returnValue = null;
|
|
||||||
iRefArgs = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
returnValue = returnValues[0];
|
|
||||||
iRefArgs = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sets the value of out and ref parameters (from
|
|
||||||
// the values returned by the Lua function).
|
|
||||||
for (int i = 0; i < outArgs.Length; i++)
|
|
||||||
{
|
|
||||||
args[outArgs[i]] = returnValues[iRefArgs];
|
|
||||||
iRefArgs++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
namespace NLua.Method
|
|
||||||
{
|
|
||||||
public class LuaEventHandler
|
|
||||||
{
|
|
||||||
public LuaFunction Handler = null;
|
|
||||||
|
|
||||||
public void HandleEvent(object[] args)
|
|
||||||
{
|
|
||||||
Handler.Call(args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,355 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
using NLua.Exceptions;
|
|
||||||
using NLua.Extensions;
|
|
||||||
|
|
||||||
using LuaState = KeraLua.Lua;
|
|
||||||
using LuaNativeFunction = KeraLua.LuaFunction;
|
|
||||||
|
|
||||||
namespace NLua.Method
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Argument extraction with type-conversion function
|
|
||||||
*/
|
|
||||||
delegate object ExtractValue(LuaState luaState, int stackPos);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Wrapper class for methods/constructors accessed from Lua.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class LuaMethodWrapper
|
|
||||||
{
|
|
||||||
internal LuaNativeFunction InvokeFunction;
|
|
||||||
|
|
||||||
readonly ObjectTranslator _translator;
|
|
||||||
readonly MethodBase _method;
|
|
||||||
|
|
||||||
readonly ExtractValue _extractTarget;
|
|
||||||
readonly object _target;
|
|
||||||
readonly bool _isStatic;
|
|
||||||
|
|
||||||
readonly string _methodName;
|
|
||||||
readonly MethodInfo[] _members;
|
|
||||||
|
|
||||||
private MethodCache _lastCalledMethod;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Constructs the wrapper for a known MethodBase instance
|
|
||||||
*/
|
|
||||||
public LuaMethodWrapper(ObjectTranslator translator, object target, ProxyType targetType, MethodBase method)
|
|
||||||
{
|
|
||||||
InvokeFunction = Call;
|
|
||||||
_translator = translator;
|
|
||||||
_target = target;
|
|
||||||
_extractTarget = translator.typeChecker.GetExtractor(targetType);
|
|
||||||
_lastCalledMethod = new MethodCache();
|
|
||||||
|
|
||||||
_method = method;
|
|
||||||
_methodName = method.Name;
|
|
||||||
_isStatic = method.IsStatic;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Constructs the wrapper for a known method name
|
|
||||||
*/
|
|
||||||
public LuaMethodWrapper(ObjectTranslator translator, ProxyType targetType, string methodName, BindingFlags bindingType)
|
|
||||||
{
|
|
||||||
InvokeFunction = Call;
|
|
||||||
|
|
||||||
_translator = translator;
|
|
||||||
_methodName = methodName;
|
|
||||||
_extractTarget = translator.typeChecker.GetExtractor(targetType);
|
|
||||||
_lastCalledMethod = new MethodCache();
|
|
||||||
|
|
||||||
_isStatic = (bindingType & BindingFlags.Static) == BindingFlags.Static;
|
|
||||||
MethodInfo [] methods = GetMethodsRecursively(targetType.UnderlyingSystemType,
|
|
||||||
methodName,
|
|
||||||
bindingType | BindingFlags.Public);
|
|
||||||
_members = ReorderMethods(methods);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static MethodInfo[] ReorderMethods(MethodInfo[] m)
|
|
||||||
{
|
|
||||||
int len = m.Length;
|
|
||||||
|
|
||||||
if (len < 2)
|
|
||||||
return m;
|
|
||||||
|
|
||||||
return m.
|
|
||||||
GroupBy(c => c.GetParameters().Length).
|
|
||||||
SelectMany(g => g.OrderByDescending(ci => ci.ToString())).
|
|
||||||
ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
MethodInfo[] GetMethodsRecursively(Type type, string methodName, BindingFlags bindingType)
|
|
||||||
{
|
|
||||||
if (type == typeof(object))
|
|
||||||
return type.GetMethods(methodName, bindingType);
|
|
||||||
|
|
||||||
var methods = type.GetMethods(methodName, bindingType);
|
|
||||||
var baseMethods = GetMethodsRecursively(type.BaseType, methodName, bindingType);
|
|
||||||
|
|
||||||
return methods.Concat(baseMethods).ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Convert C# exceptions into Lua errors
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>num of things on stack</returns>
|
|
||||||
/// <param name="e">null for no pending exception</param>
|
|
||||||
int SetPendingException(Exception e)
|
|
||||||
{
|
|
||||||
return _translator.interpreter.SetPendingException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FillMethodArguments(LuaState luaState, int numStackToSkip)
|
|
||||||
{
|
|
||||||
object[] args = _lastCalledMethod.args;
|
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < _lastCalledMethod.argTypes.Length; i++)
|
|
||||||
{
|
|
||||||
MethodArgs type = _lastCalledMethod.argTypes[i];
|
|
||||||
|
|
||||||
int index = i + 1 + numStackToSkip;
|
|
||||||
|
|
||||||
|
|
||||||
if (_lastCalledMethod.argTypes[i].IsParamsArray)
|
|
||||||
{
|
|
||||||
int count = _lastCalledMethod.argTypes.Length - i;
|
|
||||||
Array paramArray = _translator.TableToArray(luaState, type.ExtractValue, type.ParameterType, index, count);
|
|
||||||
args[_lastCalledMethod.argTypes[i].Index] = paramArray;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
args[type.Index] = type.ExtractValue(luaState, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_lastCalledMethod.args[_lastCalledMethod.argTypes[i].Index] == null &&
|
|
||||||
!luaState.IsNil(i + 1 + numStackToSkip))
|
|
||||||
throw new LuaException(string.Format("Argument number {0} is invalid", (i + 1)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int PushReturnValue(LuaState luaState)
|
|
||||||
{
|
|
||||||
int nReturnValues = 0;
|
|
||||||
// Pushes out and ref return values
|
|
||||||
for (int index = 0; index < _lastCalledMethod.outList.Length; index++)
|
|
||||||
{
|
|
||||||
nReturnValues++;
|
|
||||||
_translator.Push(luaState, _lastCalledMethod.args[_lastCalledMethod.outList[index]]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If not return void,we need add 1,
|
|
||||||
// or we will lost the function's return value
|
|
||||||
// when call dotnet function like "int foo(arg1,out arg2,out arg3)" in Lua code
|
|
||||||
if (!_lastCalledMethod.IsReturnVoid && nReturnValues > 0)
|
|
||||||
nReturnValues++;
|
|
||||||
|
|
||||||
return nReturnValues < 1 ? 1 : nReturnValues;
|
|
||||||
}
|
|
||||||
|
|
||||||
int CallInvoke(LuaState luaState, MethodBase method, object targetObject)
|
|
||||||
{
|
|
||||||
if (!luaState.CheckStack(_lastCalledMethod.outList.Length + 6))
|
|
||||||
throw new LuaException("Lua stack overflow");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
object result;
|
|
||||||
|
|
||||||
if (method.IsConstructor)
|
|
||||||
result = ((ConstructorInfo)method).Invoke(_lastCalledMethod.args);
|
|
||||||
else
|
|
||||||
result = method.Invoke(targetObject, _lastCalledMethod.args);
|
|
||||||
|
|
||||||
_translator.Push(luaState, result);
|
|
||||||
}
|
|
||||||
catch (TargetInvocationException e)
|
|
||||||
{
|
|
||||||
// Failure of method invocation
|
|
||||||
if (_translator.interpreter.UseTraceback)
|
|
||||||
e.GetBaseException().Data["Traceback"] = _translator.interpreter.GetDebugTraceback();
|
|
||||||
return SetPendingException(e.GetBaseException());
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
return SetPendingException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return PushReturnValue(luaState);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsMethodCached(LuaState luaState, int numArgsPassed, int skipParams)
|
|
||||||
{
|
|
||||||
if (_lastCalledMethod.cachedMethod == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (numArgsPassed != _lastCalledMethod.argTypes.Length)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// If there is no method overloads, is ok to use the cached method
|
|
||||||
if (_members.Length == 1)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return _translator.MatchParameters(luaState, _lastCalledMethod.cachedMethod, _lastCalledMethod, skipParams);
|
|
||||||
}
|
|
||||||
|
|
||||||
int CallMethodFromName(LuaState luaState)
|
|
||||||
{
|
|
||||||
object targetObject = null;
|
|
||||||
|
|
||||||
if (!_isStatic)
|
|
||||||
targetObject = _extractTarget(luaState, 1);
|
|
||||||
|
|
||||||
int numStackToSkip =
|
|
||||||
_isStatic
|
|
||||||
? 0
|
|
||||||
: 1; // If this is an instance invoe we will have an extra arg on the stack for the targetObject
|
|
||||||
int numArgsPassed = luaState.GetTop() - numStackToSkip;
|
|
||||||
|
|
||||||
// Cached?
|
|
||||||
if (IsMethodCached(luaState, numArgsPassed, numStackToSkip))
|
|
||||||
{
|
|
||||||
MethodBase method = _lastCalledMethod.cachedMethod;
|
|
||||||
|
|
||||||
if (!luaState.CheckStack(_lastCalledMethod.outList.Length + 6))
|
|
||||||
throw new LuaException("Lua stack overflow");
|
|
||||||
|
|
||||||
FillMethodArguments(luaState, numStackToSkip);
|
|
||||||
|
|
||||||
return CallInvoke(luaState, method, targetObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we are running an instance variable, we can now pop the targetObject from the stack
|
|
||||||
if (!_isStatic)
|
|
||||||
{
|
|
||||||
if (targetObject == null)
|
|
||||||
{
|
|
||||||
_translator.ThrowError(luaState,
|
|
||||||
string.Format("instance method '{0}' requires a non null target object", _methodName));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
luaState.Remove(1); // Pops the receiver
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hasMatch = false;
|
|
||||||
string candidateName = null;
|
|
||||||
|
|
||||||
foreach (var member in _members)
|
|
||||||
{
|
|
||||||
if (member.ReflectedType == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
candidateName = member.ReflectedType.Name + "." + member.Name;
|
|
||||||
bool isMethod = _translator.MatchParameters(luaState, member, _lastCalledMethod, 0);
|
|
||||||
|
|
||||||
if (isMethod)
|
|
||||||
{
|
|
||||||
hasMatch = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasMatch)
|
|
||||||
{
|
|
||||||
string msg = (candidateName == null)
|
|
||||||
? "Invalid arguments to method call"
|
|
||||||
: ("Invalid arguments to method: " + candidateName);
|
|
||||||
_translator.ThrowError(luaState, msg);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_lastCalledMethod.cachedMethod.ContainsGenericParameters)
|
|
||||||
return CallInvokeOnGenericMethod(luaState, (MethodInfo)_lastCalledMethod.cachedMethod, targetObject);
|
|
||||||
|
|
||||||
return CallInvoke(luaState, _lastCalledMethod.cachedMethod, targetObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
int CallInvokeOnGenericMethod(LuaState luaState, MethodInfo methodToCall, object targetObject)
|
|
||||||
{
|
|
||||||
//need to make a concrete type of the generic method definition
|
|
||||||
var typeArgs = new List<Type>();
|
|
||||||
|
|
||||||
ParameterInfo [] parameters = methodToCall.GetParameters();
|
|
||||||
|
|
||||||
for (int i = 0; i < parameters.Length; i++)
|
|
||||||
{
|
|
||||||
ParameterInfo parameter = parameters[i];
|
|
||||||
|
|
||||||
if (!parameter.ParameterType.IsGenericParameter)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
typeArgs.Add(_lastCalledMethod.args[i].GetType());
|
|
||||||
}
|
|
||||||
|
|
||||||
MethodInfo concreteMethod = methodToCall.MakeGenericMethod(typeArgs.ToArray());
|
|
||||||
|
|
||||||
_translator.Push(luaState, concreteMethod.Invoke(targetObject, _lastCalledMethod.args));
|
|
||||||
|
|
||||||
return PushReturnValue(luaState);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Calls the method. Receives the arguments from the Lua stack
|
|
||||||
* and returns values in it.
|
|
||||||
*/
|
|
||||||
int Call(IntPtr state)
|
|
||||||
{
|
|
||||||
var luaState = LuaState.FromIntPtr(state);
|
|
||||||
|
|
||||||
MethodBase methodToCall = _method;
|
|
||||||
object targetObject = _target;
|
|
||||||
|
|
||||||
if (!luaState.CheckStack(5))
|
|
||||||
throw new LuaException("Lua stack overflow");
|
|
||||||
|
|
||||||
SetPendingException(null);
|
|
||||||
|
|
||||||
// Method from name
|
|
||||||
if (methodToCall == null)
|
|
||||||
return CallMethodFromName(luaState);
|
|
||||||
|
|
||||||
// Method from MethodBase instance
|
|
||||||
if (!methodToCall.ContainsGenericParameters)
|
|
||||||
{
|
|
||||||
if (!methodToCall.IsStatic && !methodToCall.IsConstructor && targetObject == null)
|
|
||||||
{
|
|
||||||
targetObject = _extractTarget(luaState, 1);
|
|
||||||
luaState.Remove(1); // Pops the receiver
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_translator.MatchParameters(luaState, methodToCall, _lastCalledMethod, 0))
|
|
||||||
{
|
|
||||||
_translator.ThrowError(luaState, "Invalid arguments to method call");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!methodToCall.IsGenericMethodDefinition)
|
|
||||||
{
|
|
||||||
_translator.ThrowError(luaState,
|
|
||||||
"Unable to invoke method on generic class as the current method is an open generic method");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
_translator.MatchParameters(luaState, methodToCall, _lastCalledMethod, 0);
|
|
||||||
|
|
||||||
return CallInvokeOnGenericMethod(luaState, (MethodInfo) methodToCall, targetObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_isStatic)
|
|
||||||
targetObject = null;
|
|
||||||
|
|
||||||
return CallInvoke(luaState, _lastCalledMethod.cachedMethod, targetObject);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace NLua.Method
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Parameter information
|
|
||||||
*/
|
|
||||||
class MethodArgs
|
|
||||||
{
|
|
||||||
// Position of parameter
|
|
||||||
public int Index;
|
|
||||||
public Type ParameterType;
|
|
||||||
|
|
||||||
// Type-conversion function
|
|
||||||
public ExtractValue ExtractValue;
|
|
||||||
public bool IsParamsArray;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Reflection;
|
|
||||||
using NLua.Extensions;
|
|
||||||
|
|
||||||
namespace NLua.Method
|
|
||||||
{
|
|
||||||
class MethodCache
|
|
||||||
{
|
|
||||||
public MethodCache()
|
|
||||||
{
|
|
||||||
args = new object[0];
|
|
||||||
argTypes = new MethodArgs[0];
|
|
||||||
outList = new int[0];
|
|
||||||
}
|
|
||||||
private MethodBase _cachedMethod;
|
|
||||||
|
|
||||||
public MethodBase cachedMethod {
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _cachedMethod;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_cachedMethod = value;
|
|
||||||
var mi = value as MethodInfo;
|
|
||||||
|
|
||||||
if (mi != null)
|
|
||||||
{
|
|
||||||
IsReturnVoid = mi.ReturnType == typeof(void);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsReturnVoid;
|
|
||||||
// List or arguments
|
|
||||||
public object[] args;
|
|
||||||
// Positions of out parameters
|
|
||||||
public int[] outList;
|
|
||||||
// Types of parameters
|
|
||||||
public MethodArgs[] argTypes;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,53 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace NLua.Method
|
|
||||||
{
|
|
||||||
class RegisterEventHandler
|
|
||||||
{
|
|
||||||
private readonly EventHandlerContainer _pendingEvents;
|
|
||||||
private readonly EventInfo _eventInfo;
|
|
||||||
private readonly object _target;
|
|
||||||
|
|
||||||
public RegisterEventHandler(EventHandlerContainer pendingEvents, object target, EventInfo eventInfo)
|
|
||||||
{
|
|
||||||
_target = target;
|
|
||||||
_eventInfo = eventInfo;
|
|
||||||
_pendingEvents = pendingEvents;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Adds a new event handler
|
|
||||||
*/
|
|
||||||
public Delegate Add(LuaFunction function)
|
|
||||||
{
|
|
||||||
Delegate handlerDelegate = CodeGeneration.Instance.GetDelegate(_eventInfo.EventHandlerType, function);
|
|
||||||
return Add(handlerDelegate);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Delegate Add(Delegate handlerDelegate)
|
|
||||||
{
|
|
||||||
_eventInfo.AddEventHandler(_target, handlerDelegate);
|
|
||||||
_pendingEvents.Add(handlerDelegate, this);
|
|
||||||
|
|
||||||
return handlerDelegate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Removes an existing event handler
|
|
||||||
*/
|
|
||||||
public void Remove(Delegate handlerDelegate)
|
|
||||||
{
|
|
||||||
RemovePending(handlerDelegate);
|
|
||||||
_pendingEvents.Remove(handlerDelegate);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Removes an existing event handler (without updating the pending handlers list)
|
|
||||||
*/
|
|
||||||
internal void RemovePending(Delegate handlerDelegate)
|
|
||||||
{
|
|
||||||
_eventInfo.RemoveEventHandler(_target, handlerDelegate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,44 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
|
|
||||||
using LuaState = KeraLua.Lua;
|
|
||||||
|
|
||||||
namespace NLua
|
|
||||||
{
|
|
||||||
internal class ObjectTranslatorPool
|
|
||||||
{
|
|
||||||
private static volatile ObjectTranslatorPool _instance = new ObjectTranslatorPool();
|
|
||||||
|
|
||||||
private ConcurrentDictionary<LuaState, ObjectTranslator> translators = new ConcurrentDictionary<LuaState, ObjectTranslator>();
|
|
||||||
|
|
||||||
public static ObjectTranslatorPool Instance => _instance;
|
|
||||||
|
|
||||||
|
|
||||||
public void Add(LuaState luaState, ObjectTranslator translator)
|
|
||||||
{
|
|
||||||
if(!translators.TryAdd(luaState, translator))
|
|
||||||
throw new ArgumentException("An item with the same key has already been added. ", "luaState");
|
|
||||||
}
|
|
||||||
|
|
||||||
public ObjectTranslator Find(LuaState luaState)
|
|
||||||
{
|
|
||||||
ObjectTranslator translator;
|
|
||||||
|
|
||||||
if(!translators.TryGetValue(luaState, out translator))
|
|
||||||
{
|
|
||||||
LuaState main = luaState.MainThread;
|
|
||||||
|
|
||||||
if (!translators.TryGetValue(main, out translator))
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return translator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Remove(LuaState luaState)
|
|
||||||
{
|
|
||||||
ObjectTranslator translator;
|
|
||||||
translators.TryRemove(luaState, out translator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
// Information about this assembly is defined by the following attributes.
|
|
||||||
// Change them to the values specific to your project.
|
|
||||||
|
|
||||||
#if NETFRAMEWORK
|
|
||||||
[assembly: AssemblyTitle ("NLua (.NET Framework 4.5)")]
|
|
||||||
#elif WINDOWS_UWP
|
|
||||||
[assembly: AssemblyTitle ("NLua (Windows Universal)")]
|
|
||||||
#elif __ANDROID__
|
|
||||||
[assembly: AssemblyTitle ("NLua (Xamarin.Android)")]
|
|
||||||
#elif NETCOREAPP
|
|
||||||
[assembly: AssemblyTitle ("NLua (.NET Core)")]
|
|
||||||
#elif NETSTANDARD
|
|
||||||
[assembly: AssemblyTitle ("NLua (.NET Standard)")]
|
|
||||||
#elif __TVOS__
|
|
||||||
[assembly: AssemblyTitle ("NLua (Xamarin.tvOS)")]
|
|
||||||
#elif __WATCHOS__
|
|
||||||
[assembly: AssemblyTitle ("NLua (Xamarin.watchOS)")]
|
|
||||||
#elif __IOS__
|
|
||||||
[assembly: AssemblyTitle ("NLua (Xamarin.iOS)")]
|
|
||||||
#elif __MACOS__
|
|
||||||
[assembly: AssemblyTitle ("NLua (Xamarin.Mac)")]
|
|
||||||
#else
|
|
||||||
[assembly: AssemblyTitle ("NLua (.NET Framework)")]
|
|
||||||
#endif
|
|
||||||
|
|
||||||
[assembly: AssemblyDescription ("NLua library")]
|
|
||||||
[assembly: AssemblyCompany ("NLua.org")]
|
|
||||||
[assembly: AssemblyProduct ("NLua")]
|
|
||||||
[assembly: AssemblyCopyright ("Copyright © Vinicius Jarina 2020")]
|
|
||||||
[assembly: AssemblyCulture ("")]
|
|
||||||
|
|
||||||
|
|
||||||
[assembly: AssemblyVersion("1.4.1.0")]
|
|
||||||
[assembly: AssemblyInformationalVersion("1.0.7+Branch.master.Sha.80a328a64f12ed9032a0f14a75e6ecad967514d0")]
|
|
||||||
[assembly: AssemblyFileVersion("1.4.1.0")]
|
|
||||||
|
|
||||||
|
|
|
@ -1,53 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace NLua
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Summary description for ProxyType.
|
|
||||||
/// </summary>
|
|
||||||
public class ProxyType
|
|
||||||
{
|
|
||||||
private readonly Type _proxy;
|
|
||||||
|
|
||||||
public ProxyType(Type proxy)
|
|
||||||
{
|
|
||||||
_proxy = proxy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Provide human readable short hand for this proxy object
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return "ProxyType(" + UnderlyingSystemType + ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
public Type UnderlyingSystemType => _proxy;
|
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
|
||||||
{
|
|
||||||
if (obj is Type)
|
|
||||||
return _proxy == (Type)obj;
|
|
||||||
if (obj is ProxyType)
|
|
||||||
return _proxy == ((ProxyType)obj).UnderlyingSystemType;
|
|
||||||
return _proxy.Equals(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
return _proxy.GetHashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
public MemberInfo[] GetMember(string name, BindingFlags bindingAttr)
|
|
||||||
{
|
|
||||||
return _proxy.GetMember(name, bindingAttr);
|
|
||||||
}
|
|
||||||
|
|
||||||
public MethodInfo GetMethod(string name, BindingFlags bindingAttr, Type[] signature)
|
|
||||||
{
|
|
||||||
return _proxy.GetMethod(name, bindingAttr, null, signature, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -20,42 +20,66 @@ namespace OpenSim.Region.ScriptEngine.Lua
|
||||||
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LUAEngine")]
|
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LUAEngine")]
|
||||||
class LUAEngine : INonSharedRegionModule, IScriptModule, IScriptEngine
|
class LUAEngine : INonSharedRegionModule, IScriptModule, IScriptEngine
|
||||||
{
|
{
|
||||||
|
private IConfigSource m_config = null;
|
||||||
|
|
||||||
|
private Scene m_scene = null;
|
||||||
|
|
||||||
|
private bool m_enable = true;
|
||||||
|
private bool m_sandbox = true;
|
||||||
|
|
||||||
|
public event ScriptRemoved OnScriptRemoved;
|
||||||
|
public event ObjectRemoved OnObjectRemoved;
|
||||||
|
|
||||||
#region INonSharedRegionModule
|
#region INonSharedRegionModule
|
||||||
public string Name => throw new NotImplementedException();
|
public string Name
|
||||||
|
|
||||||
public Type ReplaceableInterface => throw new NotImplementedException();
|
|
||||||
|
|
||||||
public void AddRegion(Scene scene)
|
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
get { return "LUAEngine"; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Close()
|
public Type ReplaceableInterface
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
get { return null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Initialise(IConfigSource source)
|
public void Initialise(IConfigSource source)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
if (source.Configs["LUA"] == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_config = source;
|
||||||
|
|
||||||
|
m_enable = source.Configs["LUA"].GetBoolean("Enable", m_enable);
|
||||||
|
m_sandbox = source.Configs["LUA"].GetBoolean("Sandbox", m_sandbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RegionLoaded(Scene scene)
|
public void AddRegion(Scene scene)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
if (m_scene == null)
|
||||||
|
m_scene = scene;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveRegion(Scene scene)
|
public void RemoveRegion(Scene scene)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
m_scene = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
m_scene = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegionLoaded(Scene scene)
|
||||||
|
{
|
||||||
|
if (m_scene == null)
|
||||||
|
m_scene = scene;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region IScriptModule
|
#region IScriptModule
|
||||||
public string ScriptEngineName => throw new NotImplementedException();
|
public string ScriptEngineName
|
||||||
|
{
|
||||||
public event ScriptRemoved OnScriptRemoved;
|
get { return "LUAEngine"; }
|
||||||
public event ObjectRemoved OnObjectRemoved;
|
}
|
||||||
|
|
||||||
public Dictionary<uint, float> GetObjectScriptsExecutionTimes()
|
public Dictionary<uint, float> GetObjectScriptsExecutionTimes()
|
||||||
{
|
{
|
||||||
|
@ -125,15 +149,27 @@ namespace OpenSim.Region.ScriptEngine.Lua
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region IScriptEngine
|
#region IScriptEngine
|
||||||
public Scene World => throw new NotImplementedException();
|
public Scene World
|
||||||
|
{
|
||||||
|
get { return m_scene; }
|
||||||
|
}
|
||||||
|
|
||||||
public IScriptModule ScriptModule => throw new NotImplementedException();
|
public IScriptModule ScriptModule => throw new NotImplementedException();
|
||||||
|
|
||||||
public IConfig Config => throw new NotImplementedException();
|
public IConfig Config
|
||||||
|
{
|
||||||
|
get { return m_config.Configs["LUA"]; }
|
||||||
|
}
|
||||||
|
|
||||||
public IConfigSource ConfigSource => throw new NotImplementedException();
|
public IConfigSource ConfigSource
|
||||||
|
{
|
||||||
|
get { return m_config; }
|
||||||
|
}
|
||||||
|
|
||||||
public string ScriptEnginePath => throw new NotImplementedException();
|
public string ScriptEnginePath
|
||||||
|
{
|
||||||
|
get { return "./LUAScriptEngine"; }
|
||||||
|
}
|
||||||
|
|
||||||
public string ScriptClassName => throw new NotImplementedException();
|
public string ScriptClassName => throw new NotImplementedException();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using NLua;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.ScriptEngine.Lua
|
||||||
|
{
|
||||||
|
class RunningScript
|
||||||
|
{
|
||||||
|
private SceneObjectPart m_host = null;
|
||||||
|
private InventoryItem m_item = null;
|
||||||
|
private Lua m_runtime = null;
|
||||||
|
|
||||||
|
private RunningScript(InventoryItem item, SceneObjectPart host)
|
||||||
|
{
|
||||||
|
m_host = host;
|
||||||
|
m_item = item;
|
||||||
|
|
||||||
|
m_runtime = new Lua();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue