check-in NLua to main repo

combine NLua with KeraLua (KeraLua is "gone" now I guess)
make it use the BizInvoker (so now it can properly handle the liblua5.4.so and lua54.dll names differing), also delete the liblua54.so.
minor speedup when creating a new empty table
make lua default to UTF8 internally, so we don't need to manually change the state's encoding
This commit is contained in:
CasualPokePlayer 2022-12-17 21:45:28 -08:00
parent a1da5753ee
commit 339915c013
66 changed files with 10303 additions and 67 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,19 @@
Copyright (c) 2021 Vinicius Jarina (viniciusjarina@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace>NLua</RootNamespace>
<AssemblyName>NLua</AssemblyName>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<WarningsAsErrors />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<Optimize>true</Optimize>
<DebugType>portable</DebugType>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<WarningsAsErrors />
</PropertyGroup>
<ItemGroup>
<Reference Include="BizHawk.BizInvoke" HintPath="../../output/dll/BizHawk.BizInvoke.dll" />
<Reference Include="BizHawk.Common" HintPath="../../output/dll/BizHawk.Common.dll" />
</ItemGroup>
<Import Project="../LibCommon.props" />
<PropertyGroup>
<Nullable>disable</Nullable>
</PropertyGroup>
</Project>

View File

@ -0,0 +1 @@
../.build_debug.sh

View File

@ -0,0 +1 @@
../.build_release.sh

View File

@ -0,0 +1,414 @@
using System;
using System.Collections.Generic;
using NLua.Method;
using NLua.Extensions;
namespace NLua
{
internal sealed class CheckType
{
internal readonly Dictionary<Type, ExtractValue> _extractValues = new Dictionary<Type, ExtractValue>();
internal readonly ExtractValue _extractNetObject;
internal 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(LuaThread), GetAsThread);
_extractValues.Add(typeof(LuaUserData), GetAsUserdata);
_extractNetObject = GetAsNetObject;
}
/// <summary>
/// Checks if the value at Lua stack index stackPos matches paramType,
/// returning a conversion function if it does and null otherwise.
/// </summary>
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) ||
paramType == typeof(sbyte) ||
paramType == typeof(char);
// 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.Thread)
return _extractValues[typeof(LuaThread)];
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.IsNumericType(stackPos) && !netParamIsString)
return _extractValues[paramType];
}
else if (paramType == typeof(bool))
{
if (luaState.IsBoolean(stackPos))
return _extractValues[paramType];
}
else if (netParamIsString)
{
if (luaState.IsStringOrNumber(stackPos) || luatype == LuaType.Nil)
return _extractValues[paramType];
}
else if (paramType == typeof(LuaTable))
{
if (luatype == LuaType.Table || luatype == LuaType.Nil)
return _extractValues[paramType];
}
else if (paramType == typeof(LuaThread))
{
if (luatype == LuaType.Thread || 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;
}
object netObj = _translator.GetNetObject(luaState, stackPos);
if (netObj != null && paramType.IsInstanceOfType(netObj))
return _extractNetObject;
return null;
}
/// <summary>
/// The following functions return the value in the Lua stack
/// index stackPos as the desired type if it can, or null
/// otherwise.
/// </summary>
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.IsStringOrNumber(stackPos))
return null;
string retVal = luaState.ToString(stackPos, false);
return retVal.ToCharArray();
}
private object GetAsByteArray(LuaState luaState, int stackPos)
{
if (!luaState.IsStringOrNumber(stackPos))
return null;
byte [] retVal = luaState.ToBuffer(stackPos, false);
return retVal;
}
private object GetAsString(LuaState luaState, int stackPos)
{
if (!luaState.IsStringOrNumber(stackPos))
return null;
return luaState.ToString(stackPos, false);
}
private object GetAsTable(LuaState luaState, int stackPos)
{
return _translator.GetTable(luaState, stackPos);
}
private object GetAsThread(LuaState luaState, int stackPos)
{
return _translator.GetThread(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;
}
}
}

View File

@ -0,0 +1,20 @@
using System;
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; }
}
}

View File

@ -0,0 +1,14 @@
using System;
namespace NLua.Event
{
public class HookExceptionEventArgs : EventArgs
{
public Exception Exception { get; }
public HookExceptionEventArgs(Exception ex)
{
Exception = ex;
}
}
}

View File

@ -0,0 +1,20 @@
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)
{
}
}
}

View File

@ -0,0 +1,52 @@
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;
}
}
}

View File

@ -0,0 +1,119 @@
using System;
using System.Runtime.InteropServices;
namespace NLua.Extensions
{
internal 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;
}
}
}

View File

@ -0,0 +1,31 @@
using System.Collections.Generic;
namespace NLua.Extensions
{
internal 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);
}
}
}

View File

@ -0,0 +1,142 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace NLua.Extensions
{
internal 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));
}
}
// this thing is complex and not sure recommended changes are safe
#pragma warning disable MA0029 // Combine LINQ methods
#pragma warning disable BHI1002 // Do not use anonymous types (classes)
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);
#pragma warning restore BHI1002 // Do not use anonymous types (classes)
#pragma warning restore MA0029 // Combine LINQ methods
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];
}
}
}

View File

@ -0,0 +1,21 @@
using System;
namespace NLua
{
internal 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));
}
}
}

View File

@ -0,0 +1,190 @@
using System;
using System.Threading;
using System.Reflection;
using System.Reflection.Emit;
using System.Collections.Generic;
using NLua.Method;
namespace NLua
{
internal class CodeGeneration
{
private readonly Dictionary<Type, LuaClassType> _classCollection = new Dictionary<Type, LuaClassType>();
private readonly Dictionary<Type, Type> _delegateCollection = new Dictionary<Type, Type>();
static CodeGeneration()
{
}
private CodeGeneration()
{
}
/// <summary>
/// Singleton instance of the class
/// </summary>
public static CodeGeneration Instance { get; } = new CodeGeneration();
/// <summary>
/// Generates an event handler that calls a Lua function
/// </summary>
private Type GenerateEvent(Type eventHandlerType)
{
throw new NotImplementedException("Emit not available on .NET Standard ");
}
/// <summary>
/// Generates a type that can be used for instantiating a delegate
/// of the provided type, given a Lua function.
/// </summary>
private Type GenerateDelegate(Type delegateType)
{
throw new NotImplementedException("GenerateDelegate is not available on Windows Store, please register your LuaDelegate type with Lua.RegisterLuaDelegateType( yourDelegate, theLuaDelegateHandler) ");
}
internal 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)
{
throw new NotImplementedException (" Emit not available on .NET Standard ");
}
internal 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();
}
/// <summary>
/// Gets an event handler for the event type that delegates to the eventHandler Lua function.
/// Caches the generated type.
/// </summary>
public LuaEventHandler GetEvent(Type eventHandlerType, LuaFunction eventHandler)
{
throw new NotImplementedException("Emit not available on .NET Standard");
}
public void RegisterLuaDelegateType(Type delegateType, Type luaDelegateType)
{
_delegateCollection[delegateType] = luaDelegateType;
}
public void RegisterLuaClassType(Type klass, Type luaClass)
{
LuaClassType luaClassType = default;
luaClassType.klass = luaClass;
GetReturnTypesFromClass(klass, out luaClassType.returnTypes);
_classCollection[klass] = luaClassType;
}
/// <summary>
/// Gets a delegate with delegateType that calls the luaFunc Lua function
/// Caches the generated type.
/// </summary>
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");
}
/// <summary>
/// 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.
/// </summary>
public object GetClassInstance(Type klass, LuaTable luaTable)
{
LuaClassType luaClassType;
if (_classCollection.ContainsKey(klass))
luaClassType = _classCollection[klass];
else
{
luaClassType = default;
GenerateClass(klass, out luaClassType.klass, out luaClassType.returnTypes);
_classCollection[klass] = luaClassType;
}
return Activator.CreateInstance(luaClassType.klass, new object[] {
luaTable,
luaClassType.returnTypes
});
}
}
}

View File

@ -0,0 +1,21 @@
using System;
namespace NLua
{
internal 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));
}
}
}

View File

@ -0,0 +1,11 @@
namespace NLua
{
/// <summary>
/// Common interface for types generated from tables. The method
/// returns the table that overrides some or all of the type's methods.
/// </summary>
public interface ILuaGeneratedType
{
LuaTable LuaInterfaceGetLuaTable();
}
}

View File

@ -0,0 +1,15 @@
using System;
namespace NLua
{
/// <summary>
/// Structure to store a type and the return types of
/// its methods (the type of the returned value and out/ref
/// parameters).
/// </summary>
internal struct LuaClassType
{
public Type klass;
public Type[][] returnTypes;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,88 @@
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;
internal 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);
}
internal 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;
}
}
}

View File

@ -0,0 +1,87 @@
using System;
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;
}
/// <summary>
/// Calls the function casting return values to the types
/// in returnTypes
/// </summary>
internal object[] Call(object[] args, Type[] returnTypes)
{
Lua lua;
if (!TryGet(out lua))
return null;
return lua.CallFunction(this, args, returnTypes);
}
/// <summary>
/// Calls the function and returns its return values inside
/// an array
/// </summary>
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();
}
}
}

View File

@ -0,0 +1,23 @@
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; }
}
}

View File

@ -0,0 +1,201 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace NLua
{
public class LuaGlobalEntry
{
/// <summary>
/// Type at time of registration.
/// </summary>
public Type Type { get; private set; }
public string Path { get; private set; }
/// <summary>
/// List of global properties 'owned' by this entry.
/// If this entry is removed all these globals should be removed as well.
/// </summary>
public List<string> linkedGlobals = new List<string>();
public LuaGlobalEntry(Type type, string path)
{
Type = type;
Path = path;
}
}
public class LuaGlobals
{
private List<string> _globals = new List<string>();
private List<LuaGlobalEntry> _knownTypes = new List<LuaGlobalEntry>();
public bool _globalsSorted = false;
public int MaximumRecursion { get; set; } = 2;
public IEnumerable<string> Globals
{
get
{
// Only sort list when necessary
if (!_globalsSorted)
{
_globals.Sort();
_globalsSorted = true;
}
return _globals;
}
}
public bool Contains(string fullPath)
{
return _globals.Contains(fullPath);
}
public void RemoveGlobal(string path)
{
var knownType = GetKnownType(path);
if (knownType != null)
{
// We need to clean up the globals
foreach (var dependent in knownType.linkedGlobals)
{
_globals.Remove(dependent);
}
_knownTypes.Remove(knownType);
}
}
private LuaGlobalEntry GetKnownType(string path)
{
return _knownTypes.Find(x => x.Path.Equals(path));
}
public void RegisterGlobal(string path, Type type, int recursionCounter)
{
var knownType = GetKnownType(path);
if (knownType != null)
{
if (type.Equals(knownType.Type))
{
// Object is set to same value so no need to update
return;
}
// Path changed type so we should clean up all known globals associated with the type
RemoveGlobal(path);
}
RegisterPath(path, type, recursionCounter);
// List will need to be sorted on next access
_globalsSorted = false;
}
private void RegisterPath(string path, Type type, int recursionCounter, LuaGlobalEntry entry = null)
{
// If the type is a global method, list it directly
if (type == typeof(LuaFunction))
{
RegisterLuaFunction(path, entry);
}
// If the type is a class or an interface and recursion hasn't been running too long, list the members
else if ((type.IsClass || type.IsInterface) && type != typeof(string) && recursionCounter < MaximumRecursion)
{
RegisterClassOrInterface(path, type, recursionCounter, entry);
}
else
{
RegisterPrimitive(path, entry);
}
}
private void RegisterLuaFunction(string path, LuaGlobalEntry entry = null)
{
// Format for easy method invocation
_globals.Add(path + "(");
if (entry != null)
{
entry.linkedGlobals.Add(path);
}
}
private void RegisterPrimitive(string path, LuaGlobalEntry entry = null)
{
_globals.Add(path);
if (entry != null)
{
entry.linkedGlobals.Add(path);
}
}
private void RegisterClassOrInterface(string path, Type type, int recursionCounter, LuaGlobalEntry entry = null)
{
if (entry == null)
{
entry = new LuaGlobalEntry(type, path);
_knownTypes.Add(entry);
}
foreach (var method in type.GetMethods(BindingFlags.Public | BindingFlags.Instance))
{
string name = method.Name;
if (
// Check that the LuaHideAttribute and LuaGlobalAttribute were not applied
(!method.GetCustomAttributes(typeof(LuaHideAttribute), false).Any()) &&
(!method.GetCustomAttributes(typeof(LuaGlobalAttribute), false).Any()) &&
// Exclude some generic .NET methods that wouldn't be very usefull in Lua
name != "GetType" && name != "GetHashCode" && name != "Equals" &&
name != "ToString" && name != "Clone" && name != "Dispose" &&
name != "GetEnumerator" && name != "CopyTo" &&
!name.StartsWith("get_", StringComparison.Ordinal) &&
!name.StartsWith("set_", StringComparison.Ordinal) &&
!name.StartsWith("add_", StringComparison.Ordinal) &&
!name.StartsWith("remove_", StringComparison.Ordinal))
{
// Format for easy method invocation
string command = path + ":" + name + "(";
if (method.GetParameters().Length == 0)
command += ")";
_globals.Add(command);
entry.linkedGlobals.Add(command);
}
}
foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.Instance))
{
if (
// Check that the LuaHideAttribute and LuaGlobalAttribute were not applied
(!field.GetCustomAttributes(typeof(LuaHideAttribute), false).Any()) &&
(!field.GetCustomAttributes(typeof(LuaGlobalAttribute), false).Any()))
{
// Go into recursion for members
RegisterPath(path + "." + field.Name, field.FieldType, recursionCounter + 1, entry);
}
}
foreach (var property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
if (
// Check that the LuaHideAttribute and LuaGlobalAttribute were not applied
(!property.GetCustomAttributes(typeof(LuaHideAttribute), false).Any()) &&
(!property.GetCustomAttributes(typeof(LuaGlobalAttribute), false).Any())
// Exclude some generic .NET properties that wouldn't be very useful in Lua
&& property.Name != "Item")
{
// Go into recursion for members
RegisterPath(path + "." + property.Name, property.PropertyType, recursionCounter + 1, entry);
}
}
}
}
}

View File

@ -0,0 +1,12 @@
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
{
}
}

View File

@ -0,0 +1,89 @@
using System;
using System.Reflection;
using System.Diagnostics.CodeAnalysis;
namespace NLua
{
public static class LuaRegistrationHelper
{
/// <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)
{
if (lua == null)
throw new ArgumentNullException(nameof(lua));
if (o == null)
throw new ArgumentNullException(nameof(o));
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
}
}
}
/// <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)
{
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));
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
}
}
}
/// <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 InvalidOperationException($"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]);
}
}
}
}

View File

@ -0,0 +1,115 @@
using System;
using System.Collections;
using NLua.Extensions;
namespace NLua
{
public class LuaTable : LuaBase
{
public LuaTable(int reference, Lua interpreter): base(reference, interpreter)
{
}
/// <summary>
/// Indexer for string fields of the table
/// </summary>
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);
}
}
/// <summary>
/// Indexer for numeric fields of the table
/// </summary>
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 Array.Empty<object>();
return lua.GetTableDict(this).Values;
}
}
/// <summary>
/// Gets an string fields of a table ignoring its metatable,
/// if it exists
/// </summary>
internal object RawGet(string field)
{
Lua lua;
if (!TryGet(out lua))
return null;
return lua.RawGetObject(_Reference, field);
}
/// <summary>
/// Pushes this table into the Lua stack
/// </summary>
internal void Push(LuaState luaState)
{
luaState.GetRef(_Reference);
}
public override string ToString()
{
return "table";
}
}
}

View File

@ -0,0 +1,177 @@
using System;
using NLua.Exceptions;
using NLua.Extensions;
namespace NLua
{
public class LuaThread : LuaBase, IEquatable<LuaThread>, IEquatable<LuaState>, IEquatable<Lua>
{
private LuaState _luaState;
private ObjectTranslator _translator;
public LuaState State => _luaState;
/// <summary>
/// Get the main thread object
/// </summary>
public LuaThread MainThread
{
get
{
LuaState mainThread = _luaState.MainThread;
int oldTop = mainThread.GetTop();
mainThread.PushThread();
object returnValue = _translator.GetObject(mainThread, -1);
mainThread.SetTop(oldTop);
return (LuaThread)returnValue;
}
}
public LuaThread(int reference, Lua interpreter): base(reference, interpreter)
{
_luaState = interpreter.GetThreadState(reference);
_translator = interpreter.Translator;
}
/*
* Resumes this thread
*/
public LuaStatus Resume()
{
// We leave nothing on the stack if we error
var oldMainTop = _luaState.MainThread.GetTop();
var oldCoTop = _luaState.GetTop();
LuaStatus ret = _luaState.Resume(null, 0);
if (ret == LuaStatus.OK || ret == LuaStatus.Yield)
{
return ret;
}
object coErr = _translator.GetObject(_luaState, -1);
object mainErr = _translator.GetObject(_luaState.MainThread, -1);
_luaState.SetTop(oldCoTop);
_luaState.MainThread.SetTop(oldMainTop);
if (coErr is LuaScriptException coLuaEx)
{
throw coLuaEx;
}
if (mainErr is LuaScriptException mainLuaEx)
{
throw mainLuaEx;
}
if (coErr != null)
{
throw new LuaScriptException(coErr.ToString(), string.Empty);
}
throw new LuaScriptException($"Unknown Lua Error (status = {ret})", string.Empty);
}
/// <summary>
/// Yields this thread
/// </summary>
public void Yield()
{
_luaState.Yield(0);
}
/// <summary>
/// Resets this thread, cleaning its call stack and closing all pending to-be-closed variables.
/// </summary>
public int Reset()
{
int oldTop = _luaState.GetTop();
int statusCode = _luaState.ResetThread(); /* close its tbc variables */
_luaState.SetTop(oldTop);
return statusCode;
}
public void XMove(LuaState to, object val, int index = 1)
{
int oldTop = _luaState.GetTop();
_translator.Push(_luaState, val);
_luaState.XMove(to, index);
_luaState.SetTop(oldTop);
}
public void XMove(Lua to, object val, int index = 1)
{
int oldTop = _luaState.GetTop();
_translator.Push(_luaState, val);
_luaState.XMove(to.State, index);
_luaState.SetTop(oldTop);
}
public void XMove(LuaThread thread, object val, int index = 1)
{
int oldTop = _luaState.GetTop();
_translator.Push(_luaState, val);
_luaState.XMove(thread.State, index);
_luaState.SetTop(oldTop);
}
/// <summary>
/// Pushes this thread into the Lua stack
/// </summary>
internal void Push(LuaState luaState)
{
luaState.GetRef(_Reference);
}
public override string ToString()
{
return "thread";
}
public override bool Equals(object obj)
{
if (obj is LuaThread thread)
return this.State == thread.State;
else if (obj is Lua interpreter)
return this.State == interpreter.State;
else if (obj is LuaState state)
return this.State == state;
return base.Equals(obj);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
public bool Equals(LuaThread other) => this.State == other.State;
public bool Equals(LuaState other) => this.State == other;
public bool Equals(Lua other) => this.State == other.State;
public static explicit operator LuaState(LuaThread thread) => thread.State;
public static explicit operator LuaThread(Lua interpreter) => interpreter.Thread;
public static bool operator ==(LuaThread threadA, LuaThread threadB) => threadA.State == threadB.State;
public static bool operator !=(LuaThread threadA, LuaThread threadB) => threadA.State != threadB.State;
public static bool operator ==(LuaThread thread, LuaState state) => thread.State == state;
public static bool operator !=(LuaThread thread, LuaState state) => thread.State != state;
public static bool operator ==(LuaState state, LuaThread thread) => state == thread.State;
public static bool operator !=(LuaState state, LuaThread thread) => state != thread.State;
public static bool operator ==(LuaThread thread, Lua interpreter) => thread.State == interpreter.State;
public static bool operator !=(LuaThread thread, Lua interpreter) => thread.State != interpreter.State;
public static bool operator ==(Lua interpreter, LuaThread thread) => interpreter.State == thread.State;
public static bool operator !=(Lua interpreter, LuaThread thread) => interpreter.State != thread.State;
}
}

View File

@ -0,0 +1,81 @@
using NLua.Extensions;
namespace NLua
{
public class LuaUserData : LuaBase
{
public LuaUserData(int reference, Lua interpreter):base(reference, interpreter)
{
}
/// <summary>
/// Indexer for string fields of the userdata
/// </summary>
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);
}
}
/// <summary>
/// Indexer for numeric fields of the userdata
/// </summary>
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);
}
}
/// <summary>
/// Calls the userdata and returns its return values inside
/// an array
/// </summary>
public object[] Call(params object[] args)
{
Lua lua;
if (!TryGet(out lua))
return null;
return lua.CallFunction(this, args);
}
/// <summary>
/// Pushes this userdata into the Lua stack
/// </summary>
internal void Push(LuaState luaState)
{
luaState.GetRef(_Reference);
}
public override string ToString()
{
return "userdata";
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,36 @@
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>
internal 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();
}
}
}

View File

@ -0,0 +1,58 @@
using System;
namespace NLua.Method
{
public class LuaClassHelper
{
/// <summary>
/// Gets the function called name from the provided table,
/// returning null if it does not exist
/// </summary>
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;
}
/// <summary>
/// Calls the provided function with the provided parameters
/// </summary>
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 (returnValues == null || returnTypes.Length == 0)
return null;
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;
}
}
}

View File

@ -0,0 +1,47 @@
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;
}
}
}

View File

@ -0,0 +1,12 @@
namespace NLua.Method
{
public class LuaEventHandler
{
public LuaFunction Handler = null;
public void HandleEvent(object[] args)
{
Handler.Call(args);
}
}
}

View File

@ -0,0 +1,362 @@
using System;
using System.Reflection;
using System.Collections.Generic;
using System.Linq;
using NLua.Exceptions;
using NLua.Extensions;
namespace NLua.Method
{
/// <summary>
/// Argument extraction with type-conversion function
/// </summary>
internal delegate object ExtractValue(LuaState luaState, int stackPos);
/// <summary>
/// Wrapper class for methods/constructors accessed from Lua.
/// </summary>
internal class LuaMethodWrapper
{
internal LuaNativeFunction InvokeFunction;
internal readonly ObjectTranslator _translator;
internal readonly MethodBase _method;
internal readonly ExtractValue _extractTarget;
internal readonly object _target;
internal readonly bool _isStatic;
internal readonly string _methodName;
internal readonly MethodInfo[] _members;
private MethodCache _lastCalledMethod;
/// <summary>
/// Constructs the wrapper for a known MethodBase instance
/// </summary>
/// <param name="translator"></param>
/// <param name="target"></param>
/// <param name="targetType"></param>
/// <param name="method"></param>
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;
}
/// <summary>
/// Constructs the wrapper for a known method name
/// </summary>
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();
}
internal 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>
internal int SetPendingException(Exception e)
{
return _translator.interpreter.SetPendingException(e);
}
internal 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)));
}
}
internal 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;
}
internal 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);
}
internal 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 == null || _members.Length == 1)
return true;
return _translator.MatchParameters(luaState, _lastCalledMethod.cachedMethod, _lastCalledMethod, skipParams);
}
internal 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);
}
internal 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);
}
/// <summary>
/// Calls the method. Receives the arguments from the Lua stack
/// and returns values in it.
/// </summary>
internal 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
}
// Cached?
if (IsMethodCached(luaState, luaState.GetTop(), 0))
{
if (!luaState.CheckStack(_lastCalledMethod.outList.Length + 6))
throw new LuaException("Lua stack overflow");
FillMethodArguments(luaState, 0);
}
else 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);
}
}
}

View File

@ -0,0 +1,18 @@
using System;
namespace NLua.Method
{
/// <summary>
/// Parameter information
/// </summary>
internal class MethodArgs
{
// Position of parameter
public int Index;
public Type ParameterType;
// Type-conversion function
public ExtractValue ExtractValue;
public bool IsParamsArray;
}
}

View File

@ -0,0 +1,41 @@
using System;
using System.Reflection;
namespace NLua.Method
{
internal class MethodCache
{
public MethodCache()
{
args = Array.Empty<object>();
argTypes = Array.Empty<MethodArgs>();
outList = Array.Empty<int>();
}
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;
}
}

View File

@ -0,0 +1,53 @@
using System;
using System.Reflection;
namespace NLua.Method
{
internal 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;
}
/// <summary>
/// Adds a new event handler
/// </summary>
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;
}
/// <summary>
/// Removes an existing event handler
/// </summary>
public void Remove(Delegate handlerDelegate)
{
RemovePending(handlerDelegate);
_pendingEvents.Remove(handlerDelegate);
}
/// <summary>
/// Removes an existing event handler (without updating the pending handlers list)
/// </summary>
internal void RemovePending(Delegate handlerDelegate)
{
_eventInfo.RemoveEventHandler(_target, handlerDelegate);
}
}
}

View File

@ -0,0 +1,120 @@
using System;
using System.Runtime.InteropServices;
namespace NLua
{
internal static class DelegateExtensions
{
public static LuaNativeFunction ToLuaFunction(this IntPtr ptr)
{
if (ptr == IntPtr.Zero)
return null;
return Marshal.GetDelegateForFunctionPointer<LuaNativeFunction>(ptr);
}
public static IntPtr ToFunctionPointer(this LuaNativeFunction d)
{
if (d == null)
return IntPtr.Zero;
return Marshal.GetFunctionPointerForDelegate<LuaNativeFunction>(d);
}
public static LuaHookFunction ToLuaHookFunction(this IntPtr ptr)
{
if (ptr == IntPtr.Zero)
return null;
return Marshal.GetDelegateForFunctionPointer<LuaHookFunction>(ptr);
}
public static IntPtr ToFunctionPointer(this LuaHookFunction d)
{
if (d == null)
return IntPtr.Zero;
return Marshal.GetFunctionPointerForDelegate<LuaHookFunction>(d);
}
public static LuaKFunction ToLuaKFunction(this IntPtr ptr)
{
if (ptr == IntPtr.Zero)
return null;
return Marshal.GetDelegateForFunctionPointer<LuaKFunction>(ptr);
}
public static IntPtr ToFunctionPointer(this LuaKFunction d)
{
if (d == null)
return IntPtr.Zero;
return Marshal.GetFunctionPointerForDelegate<LuaKFunction>(d);
}
public static LuaReader ToLuaReader(this IntPtr ptr)
{
if (ptr == IntPtr.Zero)
return null;
return Marshal.GetDelegateForFunctionPointer<LuaReader>(ptr);
}
public static IntPtr ToFunctionPointer(this LuaReader d)
{
if (d == null)
return IntPtr.Zero;
return Marshal.GetFunctionPointerForDelegate<LuaReader>(d);
}
public static LuaWriter ToLuaWriter(this IntPtr ptr)
{
if (ptr == IntPtr.Zero)
return null;
return Marshal.GetDelegateForFunctionPointer<LuaWriter>(ptr);
}
public static IntPtr ToFunctionPointer(this LuaWriter d)
{
if (d == null)
return IntPtr.Zero;
return Marshal.GetFunctionPointerForDelegate<LuaWriter>(d);
}
public static LuaAlloc ToLuaAlloc(this IntPtr ptr)
{
if (ptr == IntPtr.Zero)
return null;
return Marshal.GetDelegateForFunctionPointer<LuaAlloc>(ptr);
}
public static IntPtr ToFunctionPointer(this LuaAlloc d)
{
if (d == null)
return IntPtr.Zero;
return Marshal.GetFunctionPointerForDelegate<LuaAlloc>(d);
}
public static LuaWarnFunction ToLuaWarning(this IntPtr ptr)
{
if (ptr == IntPtr.Zero)
return null;
return Marshal.GetDelegateForFunctionPointer<LuaWarnFunction>(ptr);
}
public static IntPtr ToFunctionPointer(this LuaWarnFunction d)
{
if (d == null)
return IntPtr.Zero;
return Marshal.GetFunctionPointerForDelegate<LuaWarnFunction>(d);
}
}
}

View File

@ -0,0 +1,86 @@
using System.Runtime.InteropServices;
using System.Security;
using charptr_t = System.IntPtr;
using lua_Debug = System.IntPtr;
using lua_KContext = System.IntPtr;
using lua_State = System.IntPtr;
using size_t = System.UIntPtr;
using voidptr_t = System.IntPtr;
namespace NLua
{
/// <summary>
/// Type for C# callbacks
/// In order to communicate properly with Lua, a C function must use the following protocol, which defines the way parameters and results are passed: a C function receives its arguments from Lua in its stack in direct order (the first argument is pushed first). So, when the function starts, lua_gettop(L) returns the number of arguments received by the function. The first argument (if any) is at index 1 and its last argument is at index lua_gettop(L). To return values to Lua, a C function just pushes them onto the stack, in direct order (the first result is pushed first), and returns the number of results. Any other value in the stack below the results will be properly discarded by Lua. Like a Lua function, a C function called by Lua can also return many results.
/// </summary>
/// <param name="luaState"></param>
/// <returns></returns>
[SuppressUnmanagedCodeSecurity]
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int LuaNativeFunction(lua_State luaState);
/// <summary>
/// Type for debugging hook functions callbacks.
/// </summary>
/// <param name="luaState"></param>
/// <param name="ar"></param>
[SuppressUnmanagedCodeSecurity]
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void LuaHookFunction(lua_State luaState, lua_Debug ar);
/// <summary>
/// Type for continuation functions
/// </summary>
/// <param name="L"></param>
/// <param name="status"></param>
/// <param name="ctx"></param>
/// <returns></returns>
[SuppressUnmanagedCodeSecurity]
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int LuaKFunction(lua_State L, int status, lua_KContext ctx);
/// <summary>
/// The reader function used by lua_load. Every time it needs another piece of the chunk, lua_load calls the reader, passing along its data parameter. The reader must return a pointer to a block of memory with a new piece of the chunk and set size to the block size
/// </summary>
/// <param name="L"></param>
/// <param name="ud"></param>
/// <param name="sz"></param>
/// <returns></returns>
[SuppressUnmanagedCodeSecurity]
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate charptr_t LuaReader(lua_State L, voidptr_t ud, ref size_t sz);
/// <summary>
///
/// </summary>
/// <param name="L"></param>
/// <param name="p"></param>
/// <param name="size"></param>
/// <param name="ud"></param>
/// <returns></returns>
[SuppressUnmanagedCodeSecurity]
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int LuaWriter(lua_State L, voidptr_t p, size_t size, voidptr_t ud);
/// <summary>
/// The type of the memory-allocation function used by Lua states. The allocator function must provide a functionality similar to realloc
/// </summary>
/// <param name="ud"></param>
/// <param name="ptr"></param>
/// <param name="osize"></param>
/// <param name="nsize"></param>
/// <returns></returns>
[SuppressUnmanagedCodeSecurity]
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate voidptr_t LuaAlloc(voidptr_t ud, voidptr_t ptr, size_t osize, size_t nsize);
/// <summary>
/// Type for warning functions
/// </summary>
/// <param name="ud"></param>
/// <param name="msg"></param>
/// <param name="tocont"></param>
[SuppressUnmanagedCodeSecurity]
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void LuaWarnFunction(voidptr_t ud, charptr_t msg, int tocont);
}

View File

@ -0,0 +1,21 @@
namespace NLua
{
/// <summary>
/// Used by Compare
/// </summary>
public enum LuaCompare
{
/// <summary>
/// compares for equality (==)
/// </summary>
Equal = 0,
/// <summary>
/// compares for less than
/// </summary>
LessThen = 1,
/// <summary>
/// compares for less or equal
/// </summary>
LessOrEqual = 2
}
}

View File

@ -0,0 +1,125 @@
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace NLua
{
/// <summary>
/// Structure for lua debug information
/// </summary>
/// <remarks>
/// Do not change this struct because it must match the lua structure lua_Debug
/// </remarks>
/// <author>Reinhard Ostermeier</author>
[StructLayout(LayoutKind.Sequential)]
public struct LuaDebug
{
/// <summary>
/// Get a LuaDebug from IntPtr
/// </summary>
/// <param name="ar"></param>
/// <returns></returns>
public static LuaDebug FromIntPtr(IntPtr ar)
{
return Marshal.PtrToStructure<LuaDebug>(ar);
}
/// <summary>
/// Debug event code
/// </summary>
[MarshalAs(UnmanagedType.I4)]
public LuaHookEvent Event;
/// <summary>
/// a reasonable name for the given function. Because functions in Lua are first-class values, they do not have a fixed name: some functions can be the value of multiple global variables, while others can be stored only in a table field
/// </summary>
public string Name => Marshal.PtrToStringAnsi(name);
internal IntPtr name;
/// <summary>
/// explains the name field. The value of namewhat can be "global", "local", "method", "field", "upvalue", or "" (the empty string)
/// </summary>
public string NameWhat => Marshal.PtrToStringAnsi(what);
internal IntPtr nameWhat;
/// <summary>
/// the string "Lua" if the function is a Lua function, "C" if it is a C function, "main" if it is the main part of a chunk
/// </summary>
public string What => Marshal.PtrToStringAnsi(what);
internal IntPtr what;
/// <summary>
/// the name of the chunk that created the function. If source starts with a '@', it means that the function was defined in a file where the file name follows the '@'.
/// </summary>
///
public string Source => Marshal.PtrToStringAnsi(source, SourceLength);
internal IntPtr source;
/// <summary>
/// The length of the string source
/// </summary>
public int SourceLength => sourceLen.ToInt32();
internal IntPtr sourceLen;
/// <summary>
/// the current line where the given function is executing. When no line information is available, currentline is set to -1
/// </summary>
public int CurrentLine;
/// <summary>
///
/// </summary>
public int LineDefined;
/// <summary>
/// the line number where the definition of the function ends.
/// </summary>
public int LastLineDefined;
/// <summary>
/// number of upvalues
/// </summary>
public byte NumberUpValues;
/// <summary>
/// number of parameters
/// </summary>
public byte NumberParameters;
/// <summary>
/// true if the function is a vararg function (always true for C functions).
/// </summary>
[MarshalAs(UnmanagedType.I1)]
public bool IsVarArg; /* (u) */
/// <summary>
/// true if this function invocation was called by a tail call. In this case, the caller of this level is not in the stack.
/// </summary>
[MarshalAs(UnmanagedType.I1)]
public bool IsTailCall; /* (t) */
/// <summary>
/// The index on the stack of the first value being "transferred", that is, parameters in a call or return values in a return. (The other values are in consecutive indices.) Using this index, you can access and modify these values through lua_getlocal and lua_setlocal. This field is only meaningful during a call hook, denoting the first parameter, or a return hook, denoting the first value being returned. (For call hooks, this value is always 1.)
/// </summary>
public ushort IndexFirstValue; /* (r) index of first value transferred */
/// <summary>
/// The number of values being transferred (see previous item). (For calls of Lua functions, this value is always equal to nparams.)
/// </summary>
public ushort NumberTransferredValues; /* (r) number of transferred values */
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 60)]
internal byte[] shortSource;
/// <summary>
/// a "printable" version of source, to be used in error messages
/// </summary>
public string ShortSource
{
get
{
if (shortSource[0] == 0)
return string.Empty;
int count = 0;
while (count < shortSource.Length && shortSource[count] != 0)
{
count++;
}
return Encoding.ASCII.GetString(shortSource, 0, count);
}
}
internal IntPtr i_ci;
}
}

View File

@ -0,0 +1,57 @@
using System;
namespace NLua
{
/// <summary>
/// Garbage Collector operations
/// </summary>
public enum LuaGC
{
/// <summary>
/// Stops the garbage collector.
/// </summary>
Stop = 0,
/// <summary>
/// Restarts the garbage collector.
/// </summary>
Restart = 1,
/// <summary>
/// Performs a full garbage-collection cycle.
/// </summary>
Collect = 2,
/// <summary>
/// Returns the current amount of memory (in Kbytes) in use by Lua.
/// </summary>
Count = 3,
/// <summary>
/// Returns the remainder of dividing the current amount of bytes of memory in use by Lua by 1024
/// </summary>
Countb = 4,
/// <summary>
/// Performs an incremental step of garbage collection.
/// </summary>
Step = 5,
/// <summary>
/// The options LUA_GCSETPAUSE and LUA_GCSETSTEPMUL of the function lua_gc are deprecated. You should use the new option LUA_GCINC to set them.
/// </summary>
[Obsolete("Deprecatad since Lua 5.4, Use Incremental instead")]
SetPause = 6,
/// <summary>
/// The options LUA_GCSETPAUSE and LUA_GCSETSTEPMUL of the function lua_gc are deprecated. You should use the new option LUA_GCINC to set them.
/// </summary>
[Obsolete("Deprecatad since Lua 5.4, Use Incremental instead")]
SetStepMultiplier = 7,
/// <summary>
/// returns a boolean that tells whether the collector is running
/// </summary>
IsRunning = 9,
/// <summary>
/// Changes the collector to generational mode with the given parameters (see §2.5.2). Returns the previous mode (LUA_GCGEN or LUA_GCINC).
/// </summary>
Generational = 10,
/// <summary>
/// Changes the collector to incremental mode with the given parameters (see §2.5.1). Returns the previous mode (LUA_GCGEN or LUA_GCINC).
/// </summary>
Incremental = 11,
}
}

View File

@ -0,0 +1,29 @@
namespace NLua
{
/// <summary>
/// Whenever a hook is called, its ar argument has its field event set to the specific event that triggered the hook
/// </summary>
public enum LuaHookEvent
{
/// <summary>
/// The call hook: is called when the interpreter calls a function. The hook is called just after Lua enters the new function, before the function gets its arguments.
/// </summary>
Call = 0,
/// <summary>
/// The return hook: is called when the interpreter returns from a function. The hook is called just before Lua leaves the function. There is no standard way to access the values to be returned by the function.
/// </summary>
Return = 1,
/// <summary>
/// The line hook: is called when the interpreter is about to start the execution of a new line of code, or when it jumps back in the code (even to the same line). (This event only happens while Lua is executing a Lua function.)
/// </summary>
Line = 2,
/// <summary>
/// The count hook: is called after the interpreter executes every count instructions. (This event only happens while Lua is executing a Lua function.)
/// </summary>
Count = 3,
/// <summary>
/// Tail Call
/// </summary>
TailCall = 4,
}
}

View File

@ -0,0 +1,32 @@
using System;
namespace NLua
{
/// <summary>
/// Lua Hook Event Masks
/// </summary>
[Flags]
public enum LuaHookMask
{
/// <summary>
/// Disabled hook
/// </summary>
Disabled = 0,
/// <summary>
/// The call hook: is called when the interpreter calls a function. The hook is called just after Lua enters the new function, before the function gets its arguments.
/// </summary>
Call = 1 << LuaHookEvent.Call,
/// <summary>
/// The return hook: is called when the interpreter returns from a function. The hook is called just before Lua leaves the function. There is no standard way to access the values to be returned by the function.
/// </summary>
Return = 1 << LuaHookEvent.Return,
/// <summary>
/// The line hook: is called when the interpreter is about to start the execution of a new line of code, or when it jumps back in the code (even to the same line). (This event only happens while Lua is executing a Lua function.)
/// </summary>
Line = 1 << LuaHookEvent.Line,
/// <summary>
/// The count hook: is called after the interpreter executes every count instructions. (This event only happens while Lua is executing a Lua function.)
/// </summary>
Count = 1 << LuaHookEvent.Count,
}
}

View File

@ -0,0 +1,67 @@
namespace NLua
{
/// <summary>
/// Operation value used by Arith method
/// </summary>
public enum LuaOperation
{
/// <summary>
/// adition(+)
/// </summary>
Add = 0,
/// <summary>
/// substraction (-)
/// </summary>
Sub = 1,
/// <summary>
/// Multiplication (*)
/// </summary>
Mul = 2,
/// <summary>
/// Modulo (%)
/// </summary>
Mod = 3,
/// <summary>
/// Exponentiation (^)
/// </summary>
Pow = 4,
/// <summary>
/// performs float division (/)
/// </summary>
Div = 5,
/// <summary>
/// performs floor division (//)
/// </summary>
Idiv = 6,
/// <summary>
/// performs bitwise AND
/// </summary>
Band = 7,
/// <summary>
/// performs bitwise OR (|)
/// </summary>
Bor = 8,
/// <summary>
/// performs bitwise exclusive OR (~)
/// </summary>
Bxor = 9,
/// <summary>
/// performs left shift
/// </summary>
Shl = 10,
/// <summary>
/// performs right shift
/// </summary>
Shr = 11,
/// <summary>
/// performs mathematical negation (unary -)
/// </summary>
Unm = 12,
/// <summary>
/// performs bitwise NOT (~)
/// </summary>
Bnot = 13,
}
}

View File

@ -0,0 +1,21 @@
using System.Runtime.InteropServices;
namespace NLua
{
/// <summary>
/// LuaRegister store the name and the delegate to register a native function
/// </summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct LuaRegister
{
/// <summary>
/// Function name
/// </summary>
public string name;
/// <summary>
/// Function delegate
/// </summary>
[MarshalAs(UnmanagedType.FunctionPtr)]
public LuaNativeFunction function;
}
}

View File

@ -0,0 +1,29 @@
namespace NLua
{
/// <summary>
/// Enum for pseudo-index used by registry table
/// </summary>
public enum LuaRegistry
{
/* LUAI_MAXSTACK 1000000 */
/// <summary>
/// pseudo-index used by registry table
/// </summary>
Index = -1000000 - 1000
}
/// <summary>
/// Registry index
/// </summary>
public enum LuaRegistryIndex
{
/// <summary>
/// At this index the registry has the main thread of the state.
/// </summary>
MainThread = 1,
/// <summary>
/// At this index the registry has the global environment.
/// </summary>
Globals = 2,
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,33 @@
namespace NLua
{
/// <summary>
/// Lua Load/Call status return
/// </summary>
public enum LuaStatus
{
/// <summary>
/// success
/// </summary>
OK = 0,
/// <summary>
/// Yield
/// </summary>
Yield = 1,
/// <summary>
/// a runtime error.
/// </summary>
ErrRun = 2,
/// <summary>
/// syntax error during precompilation
/// </summary>
ErrSyntax = 3,
/// <summary>
/// memory allocation error. For such errors, Lua does not call the message handler.
/// </summary>
ErrMem = 4,
/// <summary>
/// error while running the message handler.
/// </summary>
ErrErr = 5,
}
}

View File

@ -0,0 +1,50 @@
namespace NLua
{
/// <summary>
/// Lua types
/// </summary>
public enum LuaType
{
/// <summary>
///
/// </summary>
None = -1,
/// <summary>
/// LUA_TNIL
/// </summary>
Nil = 0,
/// <summary>
/// LUA_TBOOLEAN
/// </summary>
Boolean = 1,
/// <summary>
/// LUA_TLIGHTUSERDATA
/// </summary>
LightUserData = 2,
/// <summary>
/// LUA_TNUMBER
/// </summary>
Number = 3,
/// <summary>
/// LUA_TSTRING
/// </summary>
String = 4,
/// <summary>
/// LUA_TTABLE
/// </summary>
Table = 5,
/// <summary>
/// LUA_TFUNCTION
/// </summary>
Function = 6,
/// <summary>
/// LUA_TUSERDATA
/// </summary>
UserData = 7,
/// <summary>
/// LUA_TTHREAD
/// </summary>
/// //
Thread = 8,
}
}

View File

@ -0,0 +1,439 @@
// ReSharper disable IdentifierTypo
using System.Runtime.InteropServices;
using System.Security;
using BizHawk.BizInvoke;
using charptr_t = System.IntPtr;
using lua_Alloc = System.IntPtr;
using lua_CFunction = System.IntPtr;
using lua_Debug = System.IntPtr;
using lua_Hook = System.IntPtr;
using lua_Integer = System.Int64;
using lua_KContext = System.IntPtr;
using lua_KFunction = System.IntPtr;
using lua_Number = System.Double;
using lua_Number_ptr = System.IntPtr;
using lua_Reader = System.IntPtr;
using lua_State = System.IntPtr;
using lua_WarnFunction = System.IntPtr;
using lua_Writer = System.IntPtr;
using size_t = System.UIntPtr;
using voidptr_t = System.IntPtr;
namespace NLua
{
[SuppressUnmanagedCodeSecurity]
public abstract class NativeMethods
{
private const CallingConvention cc = CallingConvention.Cdecl;
#pragma warning disable SA1121 // Use built-in type alias
[BizImport(cc)]
public abstract int lua_absindex(lua_State luaState, int idx);
[BizImport(cc)]
public abstract void lua_arith(lua_State luaState, int op);
[BizImport(cc)]
public abstract lua_CFunction lua_atpanic(lua_State luaState, lua_CFunction panicf);
[BizImport(cc)]
public abstract void lua_callk(lua_State luaState, int nargs, int nresults, lua_KContext ctx, lua_KFunction k);
[BizImport(cc)]
public abstract int lua_checkstack(lua_State luaState, int extra);
[BizImport(cc)]
public abstract void lua_close(lua_State luaState);
[BizImport(cc)]
public abstract int lua_compare(lua_State luaState, int index1, int index2, int op);
[BizImport(cc)]
public abstract void lua_concat(lua_State luaState, int n);
[BizImport(cc)]
public abstract void lua_copy(lua_State luaState, int fromIndex, int toIndex);
[BizImport(cc)]
public abstract void lua_createtable(lua_State luaState, int elements, int records);
[BizImport(cc)]
public abstract int lua_dump(lua_State luaState, lua_Writer writer, voidptr_t data, int strip);
[BizImport(cc)]
public abstract int lua_error(lua_State luaState);
[BizImport(cc)]
public abstract int lua_gc(lua_State luaState, int what, int data);
[BizImport(cc, EntryPoint = "lua_gc")]
public abstract int lua_gc_2(lua_State luaState, int what, int data, int data2);
[BizImport(cc)]
public abstract lua_Alloc lua_getallocf(lua_State luaState, ref voidptr_t ud);
[BizImport(cc)]
public abstract int lua_getfield(lua_State luaState, int index, string k);
[BizImport(cc)]
public abstract int lua_getglobal(lua_State luaState, string name);
[BizImport(cc)]
public abstract lua_Hook lua_gethook(lua_State luaState);
[BizImport(cc)]
public abstract int lua_gethookcount(lua_State luaState);
[BizImport(cc)]
public abstract int lua_gethookmask(lua_State luaState);
[BizImport(cc)]
public abstract int lua_geti(lua_State luaState, int index, long i);
[BizImport(cc)]
public abstract int lua_getinfo(lua_State luaState, string what, lua_Debug ar);
[BizImport(cc)]
public abstract int lua_getiuservalue(lua_State luaState, int idx, int n);
[BizImport(cc)]
public abstract charptr_t lua_getlocal(lua_State luaState, lua_Debug ar, int n);
[BizImport(cc)]
public abstract int lua_getmetatable(lua_State luaState, int index);
[BizImport(cc)]
public abstract int lua_getstack(lua_State luaState, int level, lua_Debug n);
[BizImport(cc)]
public abstract int lua_gettable(lua_State luaState, int index);
[BizImport(cc)]
public abstract int lua_gettop(lua_State luaState);
[BizImport(cc)]
public abstract charptr_t lua_getupvalue(lua_State luaState, int funcIndex, int n);
[BizImport(cc)]
public abstract int lua_iscfunction(lua_State luaState, int index);
[BizImport(cc)]
public abstract int lua_isinteger(lua_State luaState, int index);
[BizImport(cc)]
public abstract int lua_isnumber(lua_State luaState, int index);
[BizImport(cc)]
public abstract int lua_isstring(lua_State luaState, int index);
[BizImport(cc)]
public abstract int lua_isuserdata(lua_State luaState, int index);
[BizImport(cc)]
public abstract int lua_isyieldable(lua_State luaState);
[BizImport(cc)]
public abstract void lua_len(lua_State luaState, int index);
[BizImport(cc)]
public abstract int lua_load
(lua_State luaState,
lua_Reader reader,
voidptr_t data,
string chunkName,
string mode);
[BizImport(cc)]
public abstract lua_State lua_newstate(lua_Alloc allocFunction, voidptr_t ud);
[BizImport(cc)]
public abstract lua_State lua_newthread(lua_State luaState);
[BizImport(cc)]
public abstract voidptr_t lua_newuserdatauv(lua_State luaState, size_t size, int nuvalue);
[BizImport(cc)]
public abstract int lua_next(lua_State luaState, int index);
[BizImport(cc)]
public abstract int lua_pcallk
(lua_State luaState,
int nargs,
int nresults,
int errorfunc,
lua_KContext ctx,
lua_KFunction k);
[BizImport(cc)]
public abstract void lua_pushboolean(lua_State luaState, int value);
[BizImport(cc)]
public abstract void lua_pushcclosure(lua_State luaState, lua_CFunction f, int n);
[BizImport(cc)]
public abstract void lua_pushinteger(lua_State luaState, lua_Integer n);
[BizImport(cc)]
public abstract void lua_pushlightuserdata(lua_State luaState, voidptr_t udata);
[BizImport(cc)]
public abstract charptr_t lua_pushlstring(lua_State luaState, byte[] s, size_t len);
[BizImport(cc)]
public abstract void lua_pushnil(lua_State luaState);
[BizImport(cc)]
public abstract void lua_pushnumber(lua_State luaState, lua_Number number);
[BizImport(cc)]
public abstract int lua_pushthread(lua_State luaState);
[BizImport(cc)]
public abstract void lua_pushvalue(lua_State luaState, int index);
[BizImport(cc)]
public abstract int lua_rawequal(lua_State luaState, int index1, int index2);
[BizImport(cc)]
public abstract int lua_rawget(lua_State luaState, int index);
[BizImport(cc)]
public abstract int lua_rawgeti(lua_State luaState, int index, lua_Integer n);
[BizImport(cc)]
public abstract int lua_rawgetp(lua_State luaState, int index, voidptr_t p);
[BizImport(cc)]
public abstract size_t lua_rawlen(lua_State luaState, int index);
[BizImport(cc)]
public abstract void lua_rawset(lua_State luaState, int index);
[BizImport(cc)]
public abstract void lua_rawseti(lua_State luaState, int index, lua_Integer i);
[BizImport(cc)]
public abstract void lua_rawsetp(lua_State luaState, int index, voidptr_t p);
[BizImport(cc)]
public abstract int lua_resetthread(lua_State luaState);
[BizImport(cc)]
public abstract int lua_resume(lua_State luaState, lua_State from, int nargs, out int results);
[BizImport(cc)]
public abstract void lua_rotate(lua_State luaState, int index, int n);
[BizImport(cc)]
public abstract void lua_setallocf(lua_State luaState, lua_Alloc f, voidptr_t ud);
[BizImport(cc)]
public abstract void lua_setfield(lua_State luaState, int index, string key);
[BizImport(cc)]
public abstract void lua_setglobal(lua_State luaState, string key);
[BizImport(cc)]
public abstract void lua_sethook(lua_State luaState, lua_Hook f, int mask, int count);
[BizImport(cc)]
public abstract void lua_seti(lua_State luaState, int index, long n);
[BizImport(cc)]
public abstract void lua_setiuservalue(lua_State luaState, int index, int n);
[BizImport(cc)]
public abstract charptr_t lua_setlocal(lua_State luaState, lua_Debug ar, int n);
[BizImport(cc)]
public abstract void lua_setmetatable(lua_State luaState, int objIndex);
[BizImport(cc)]
public abstract void lua_settable(lua_State luaState, int index);
[BizImport(cc)]
public abstract void lua_settop(lua_State luaState, int newTop);
[BizImport(cc)]
public abstract charptr_t lua_setupvalue(lua_State luaState, int funcIndex, int n);
[BizImport(cc)]
public abstract void lua_setwarnf(lua_State luaState, lua_WarnFunction warningFunctionPtr, voidptr_t ud);
[BizImport(cc)]
public abstract int lua_status(lua_State luaState);
[BizImport(cc)]
public abstract size_t lua_stringtonumber(lua_State luaState, string s);
[BizImport(cc)]
public abstract int lua_toboolean(lua_State luaState, int index);
[BizImport(cc)]
public abstract lua_CFunction lua_tocfunction(lua_State luaState, int index);
[BizImport(cc)]
public abstract lua_CFunction lua_toclose(lua_State luaState, int index);
[BizImport(cc)]
public abstract lua_Integer lua_tointegerx(lua_State luaState, int index, out int isNum);
[BizImport(cc)]
public abstract charptr_t lua_tolstring(lua_State luaState, int index, out size_t strLen);
[BizImport(cc)]
public abstract lua_Number lua_tonumberx(lua_State luaState, int index, out int isNum);
[BizImport(cc)]
public abstract voidptr_t lua_topointer(lua_State luaState, int index);
[BizImport(cc)]
public abstract lua_State lua_tothread(lua_State luaState, int index);
[BizImport(cc)]
public abstract voidptr_t lua_touserdata(lua_State luaState, int index);
[BizImport(cc)]
public abstract int lua_type(lua_State luaState, int index);
[BizImport(cc)]
public abstract charptr_t lua_typename(lua_State luaState, int type);
[BizImport(cc)]
public abstract voidptr_t lua_upvalueid(lua_State luaState, int funcIndex, int n);
[BizImport(cc)]
public abstract void lua_upvaluejoin(lua_State luaState, int funcIndex1, int n1, int funcIndex2, int n2);
[BizImport(cc)]
public abstract lua_Number lua_version(lua_State luaState);
[BizImport(cc)]
public abstract void lua_warning(lua_State luaState, string msg, int tocont);
[BizImport(cc)]
public abstract void lua_xmove(lua_State from, lua_State to, int n);
[BizImport(cc)]
public abstract int lua_yieldk(lua_State luaState,
int nresults,
lua_KContext ctx,
lua_KFunction k);
[BizImport(cc)]
public abstract int luaL_argerror(lua_State luaState, int arg, string message);
[BizImport(cc)]
public abstract int luaL_callmeta(lua_State luaState, int obj, string e);
[BizImport(cc)]
public abstract void luaL_checkany(lua_State luaState, int arg);
[BizImport(cc)]
public abstract lua_Integer luaL_checkinteger(lua_State luaState, int arg);
[BizImport(cc)]
public abstract charptr_t luaL_checklstring(lua_State luaState, int arg, out size_t len);
[BizImport(cc)]
public abstract lua_Number luaL_checknumber(lua_State luaState, int arg);
[BizImport(cc, Compatibility = true)]
public abstract int luaL_checkoption(lua_State luaState, int arg, string def, string[] list);
[BizImport(cc)]
public abstract void luaL_checkstack(lua_State luaState, int sz, string message);
[BizImport(cc)]
public abstract void luaL_checktype(lua_State luaState, int arg, int type);
[BizImport(cc)]
public abstract voidptr_t luaL_checkudata(lua_State luaState, int arg, string tName);
[BizImport(cc)]
public abstract void luaL_checkversion_(lua_State luaState, lua_Number ver, size_t sz);
[BizImport(cc)]
public abstract int luaL_error(lua_State luaState, string message);
[BizImport(cc)]
public abstract int luaL_execresult(lua_State luaState, int stat);
[BizImport(cc)]
public abstract int luaL_fileresult(lua_State luaState, int stat, string fileName);
[BizImport(cc)]
public abstract int luaL_getmetafield(lua_State luaState, int obj, string e);
[BizImport(cc)]
public abstract int luaL_getsubtable(lua_State luaState, int index, string name);
[BizImport(cc)]
public abstract lua_Integer luaL_len(lua_State luaState, int index);
[BizImport(cc)]
public abstract int luaL_loadbufferx
(lua_State luaState,
byte[] buff,
size_t sz,
string name,
string mode);
[BizImport(cc)]
public abstract int luaL_loadfilex(lua_State luaState, string name, string mode);
[BizImport(cc)]
public abstract int luaL_newmetatable(lua_State luaState, string name);
[BizImport(cc)]
public abstract lua_State luaL_newstate();
[BizImport(cc)]
public abstract void luaL_openlibs(lua_State luaState);
[BizImport(cc)]
public abstract lua_Integer luaL_optinteger(lua_State luaState, int arg, lua_Integer d);
[BizImport(cc)]
public abstract lua_Number luaL_optnumber(lua_State luaState, int arg, lua_Number d);
[BizImport(cc)]
public abstract int luaL_ref(lua_State luaState, int registryIndex);
[BizImport(cc)]
public abstract void luaL_requiref(lua_State luaState, string moduleName, lua_CFunction openFunction, int global);
[BizImport(cc, Compatibility = true)]
public abstract void luaL_setfuncs(lua_State luaState, [In] LuaRegister[] luaReg, int numUp);
[BizImport(cc)]
public abstract void luaL_setmetatable(lua_State luaState, string tName);
[BizImport(cc)]
public abstract voidptr_t luaL_testudata(lua_State luaState, int arg, string tName);
[BizImport(cc)]
public abstract charptr_t luaL_tolstring(lua_State luaState, int index, out size_t len);
[BizImport(cc)]
public abstract charptr_t luaL_traceback
(lua_State luaState,
lua_State luaState2,
string message,
int level);
[BizImport(cc)]
public abstract int luaL_typeerror(lua_State luaState, int arg, string typeName);
[BizImport(cc)]
public abstract void luaL_unref(lua_State luaState, int registryIndex, int reference);
[BizImport(cc)]
public abstract void luaL_where(lua_State luaState, int level);
#pragma warning restore SA1121 // Use built-in type alias
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,42 @@
using System;
using System.Collections.Concurrent;
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. ", nameof(luaState));
}
public ObjectTranslator Find(LuaState luaState)
{
ObjectTranslator translator;
if(!translators.TryGetValue(luaState, out translator))
{
LuaState main = luaState.MainThread;
if (!translators.TryGetValue(main, out translator))
throw new Exception("Invalid luaState, couldn't find ObjectTranslator");
}
return translator;
}
public void Remove(LuaState luaState)
{
ObjectTranslator translator;
translators.TryRemove(luaState, out translator);
}
}
}

View File

@ -0,0 +1,19 @@
using System.Reflection;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle ("NLua (.NET Standard)")]
[assembly: AssemblyDescription ("NLua library")]
[assembly: AssemblyCompany ("NLua.org")]
[assembly: AssemblyProduct ("NLua")]
[assembly: AssemblyCopyright ("Copyright © Vinicius Jarina 2021")]
[assembly: AssemblyCulture ("")]
[assembly: AssemblyVersion("1.4.1.0")]
[assembly: AssemblyInformationalVersion("1.0.7+Branch.main.Sha.80a328a64f12ed9032a0f14a75e6ecad967514d0")]
[assembly: AssemblyFileVersion("1.4.1.0")]

View File

@ -0,0 +1,50 @@
using System;
using System.Reflection;
namespace NLua
{
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);
}
}
}

Binary file not shown.

View File

@ -9,35 +9,79 @@
".NETStandard,Version=v2.0/": {
"NLua/1.0.0": {
"dependencies": {
"KeraLua": "1.3.2",
"Microsoft.SourceLink.GitHub": "1.1.0",
"NETStandard.Library": "2.0.3"
"DotNetAnalyzers.DocumentationAnalyzers": "1.0.0-beta.59",
"Menees.Analyzers": "3.0.8",
"Meziantou.Analyzer": "1.0.707",
"NETStandard.Library": "2.0.3",
"Nullable": "1.3.1",
"StyleCop.Analyzers": "1.2.0-beta.435",
"BizHawk.BizInvoke": "1.0.0.0",
"BizHawk.Common": "1.0.0.0"
},
"runtime": {
"NLua.dll": {}
}
},
"KeraLua/1.3.2": {
"runtime": {
"lib/netstandard2.0/KeraLua.dll": {
"assemblyVersion": "1.3.2.0",
"fileVersion": "1.3.2.0"
}
}
},
"Microsoft.Build.Tasks.Git/1.1.0": {},
"Microsoft.NETCore.Platforms/1.1.0": {},
"Microsoft.SourceLink.Common/1.1.0": {},
"Microsoft.SourceLink.GitHub/1.1.0": {
"DotNetAnalyzers.DocumentationAnalyzers/1.0.0-beta.59": {
"dependencies": {
"Microsoft.Build.Tasks.Git": "1.1.0",
"Microsoft.SourceLink.Common": "1.1.0"
"DotNetAnalyzers.DocumentationAnalyzers.Unstable": "1.0.0.59"
}
},
"DotNetAnalyzers.DocumentationAnalyzers.Unstable/1.0.0.59": {},
"Menees.Analyzers/3.0.8": {},
"Meziantou.Analyzer/1.0.707": {},
"Microsoft.NETCore.Platforms/1.1.0": {},
"NETStandard.Library/2.0.3": {
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0"
}
},
"Nullable/1.3.1": {},
"StyleCop.Analyzers/1.2.0-beta.435": {
"dependencies": {
"StyleCop.Analyzers.Unstable": "1.2.0.435"
}
},
"StyleCop.Analyzers.Unstable/1.2.0.435": {},
"BizHawk.BizInvoke/1.0.0.0": {
"runtime": {
"BizHawk.BizInvoke.dll": {
"assemblyVersion": "1.0.0.0",
"fileVersion": "1.0.0.0"
}
}
},
"BizHawk.Common/1.0.0.0": {
"runtime": {
"BizHawk.Common.dll": {
"assemblyVersion": "1.0.0.0",
"fileVersion": "1.0.0.0"
}
}
},
"System.Memory/4.0.1.1": {
"runtime": {
"System.Memory.dll": {
"assemblyVersion": "4.0.1.1",
"fileVersion": "4.6.28619.1"
}
}
},
"System.Numerics.Vectors/4.1.4.0": {
"runtime": {
"System.Numerics.Vectors.dll": {
"assemblyVersion": "4.1.4.0",
"fileVersion": "4.6.26515.6"
}
}
},
"System.Buffers/4.0.3.0": {
"runtime": {
"System.Buffers.dll": {
"assemblyVersion": "4.0.3.0",
"fileVersion": "4.6.28619.1"
}
}
}
}
},
@ -47,19 +91,33 @@
"serviceable": false,
"sha512": ""
},
"KeraLua/1.3.2": {
"DotNetAnalyzers.DocumentationAnalyzers/1.0.0-beta.59": {
"type": "package",
"serviceable": true,
"sha512": "sha512-NXqBDEUC2WbAE43Yx/x+PNfv80SLorUuZLU+2Y71rYSRgmY2vYfmI6+8yINYPRTrySecbaEVRQFlcGJllyYi6g==",
"path": "keralua/1.3.2",
"hashPath": "keralua.1.3.2.nupkg.sha512"
"sha512": "sha512-+cjn5bzar9cqDABF2SUsMEof8yoMXSNdHYdpCVNnj/M/cRACbKYHzYpgilSEvFlHGuolzJJ2WN++/EXwBzSsYQ==",
"path": "dotnetanalyzers.documentationanalyzers/1.0.0-beta.59",
"hashPath": "dotnetanalyzers.documentationanalyzers.1.0.0-beta.59.nupkg.sha512"
},
"Microsoft.Build.Tasks.Git/1.1.0": {
"DotNetAnalyzers.DocumentationAnalyzers.Unstable/1.0.0.59": {
"type": "package",
"serviceable": true,
"sha512": "sha512-DD84CsvKf+hfDBbYXIvBXeY7JGfbtoIMMjlPGVaKIp6aWoIdL5EJbWvk+skGkM7/Weezj3q1a89nTPAcGlGcpw==",
"path": "microsoft.build.tasks.git/1.1.0",
"hashPath": "microsoft.build.tasks.git.1.1.0.nupkg.sha512"
"sha512": "sha512-ekGYoPsAGTJs5cFbRdzfHKX2n2DzEATZyowGw3QJnozelzmhQ5tGCJhyolN5NWDq1p/GkBPKgRcQ5QGTKxaGrA==",
"path": "dotnetanalyzers.documentationanalyzers.unstable/1.0.0.59",
"hashPath": "dotnetanalyzers.documentationanalyzers.unstable.1.0.0.59.nupkg.sha512"
},
"Menees.Analyzers/3.0.8": {
"type": "package",
"serviceable": true,
"sha512": "sha512-26WtDVJZe2CEpCqJ16uR0KkCBLwDsHrr4lLSH4JZzUWoYqIQPgpwkh/9VXNJzi5bFeKn/gL0Sz77eFoNaArkhA==",
"path": "menees.analyzers/3.0.8",
"hashPath": "menees.analyzers.3.0.8.nupkg.sha512"
},
"Meziantou.Analyzer/1.0.707": {
"type": "package",
"serviceable": true,
"sha512": "sha512-8NklUjV3DHVxfyCbPYlwVtBjeNLF23lcS1QUBZt5ri1pxqr2UaVcg/uD+l0ZxwSnwTwTxX6A+Rfn+WksnBsLsg==",
"path": "meziantou.analyzer/1.0.707",
"hashPath": "meziantou.analyzer.1.0.707.nupkg.sha512"
},
"Microsoft.NETCore.Platforms/1.1.0": {
"type": "package",
@ -68,26 +126,58 @@
"path": "microsoft.netcore.platforms/1.1.0",
"hashPath": "microsoft.netcore.platforms.1.1.0.nupkg.sha512"
},
"Microsoft.SourceLink.Common/1.1.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-TyGnSaCanfxunClp2af9jpXY127q7g5tiOv0XN/JGcalyKwYusYp06BUGSmCopg/GhmJJSiR/9PS0suXHCGxtw==",
"path": "microsoft.sourcelink.common/1.1.0",
"hashPath": "microsoft.sourcelink.common.1.1.0.nupkg.sha512"
},
"Microsoft.SourceLink.GitHub/1.1.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-DD/LF81k5ODHCfPnBCds97N6KKSS1X1NiDcJYUUpiTu5mmuPktZplhYFrAPQPktMBKvNMdwFrwJ7Fqa3tyTIuA==",
"path": "microsoft.sourcelink.github/1.1.0",
"hashPath": "microsoft.sourcelink.github.1.1.0.nupkg.sha512"
},
"NETStandard.Library/2.0.3": {
"type": "package",
"serviceable": true,
"sha512": "sha512-st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==",
"path": "netstandard.library/2.0.3",
"hashPath": "netstandard.library.2.0.3.nupkg.sha512"
},
"Nullable/1.3.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-Mk4ZVDfAORTjvckQprCSehi1XgOAAlk5ez06Va/acRYEloN9t6d6zpzJRn5MEq7+RnagyFIq9r+kbWzLGd+6QA==",
"path": "nullable/1.3.1",
"hashPath": "nullable.1.3.1.nupkg.sha512"
},
"StyleCop.Analyzers/1.2.0-beta.435": {
"type": "package",
"serviceable": true,
"sha512": "sha512-TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==",
"path": "stylecop.analyzers/1.2.0-beta.435",
"hashPath": "stylecop.analyzers.1.2.0-beta.435.nupkg.sha512"
},
"StyleCop.Analyzers.Unstable/1.2.0.435": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg==",
"path": "stylecop.analyzers.unstable/1.2.0.435",
"hashPath": "stylecop.analyzers.unstable.1.2.0.435.nupkg.sha512"
},
"BizHawk.BizInvoke/1.0.0.0": {
"type": "reference",
"serviceable": false,
"sha512": ""
},
"BizHawk.Common/1.0.0.0": {
"type": "reference",
"serviceable": false,
"sha512": ""
},
"System.Memory/4.0.1.1": {
"type": "reference",
"serviceable": false,
"sha512": ""
},
"System.Numerics.Vectors/4.1.4.0": {
"type": "reference",
"serviceable": false,
"sha512": ""
},
"System.Buffers/4.0.3.0": {
"type": "reference",
"serviceable": false,
"sha512": ""
}
}
}

Binary file not shown.

View File

@ -4,6 +4,7 @@ using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using BizHawk.Common;
using BizHawk.Common.CollectionExtensions;
@ -365,6 +366,9 @@ namespace BizHawk.BizInvoke
returnType,
paramTypes);
// live dangerously
method.SetCustomAttribute(new(typeof(SuppressUnmanagedCodeSecurityAttribute).GetConstructor(Type.EmptyTypes), Array.Empty<object>()));
var il = method.GetILGenerator();
Label exc = default;

View File

@ -9,8 +9,7 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="System.Data.SQLite, Version=1.0.105.2, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=AMD64" SpecificVersion="False" HintPath="$(ProjectDir)../../References/x64/SQLite/System.Data.SQLite.dll" Private="true" />
<Reference Include="NLua, Version=1.4.1.0, Culture=neutral, PublicKeyToken=null, processorArchitecture=MSIL" SpecificVersion="false" HintPath="$(ProjectDir)../../References/NLua.dll" Private="false" />
<Reference Include="KeraLua, Version=1.3.2.0, Culture=neutral, PublicKeyToken=6a194c04b9c89217, processorArchitecture=MSIL" SpecificVersion="false" HintPath="$(ProjectDir)../../References/KeraLua.dll" Private="false" />
<Reference Include="NLua, Version=1.4.1.0, Culture=neutral, PublicKeyToken=null, processorArchitecture=MSIL" SpecificVersion="false" HintPath="$(ProjectDir)../../References/NLua.dll" Private="true" />
<PackageReference Include="SharpCompress" Version="0.30.1" />
<ProjectReference Include="$(ProjectDir)../BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj" />
<ProjectReference Include="$(ProjectDir)../BizHawk.Bizware.BizwareGL/BizHawk.Bizware.BizwareGL.csproj" />

View File

@ -22,19 +22,11 @@ namespace BizHawk.Client.Common
_lua = lua;
}
private LuaTable NewTable()
{
_lua.NewTable("__BIZHAWK_INTERNAL_TEMP_TABLE");
var ret = _lua.GetTable("__BIZHAWK_INTERNAL_TEMP_TABLE");
_lua["__BIZHAWK_INTERNAL_TEMP_TABLE"] = null;
return ret;
}
public LuaTable CreateTable() => NewTable();
public LuaTable CreateTable() => _lua.NewTable();
public LuaTable DictToTable<T>(IReadOnlyDictionary<string, T> dictionary)
{
var table = NewTable();
var table = CreateTable();
foreach (var (k, v) in dictionary) table[k] = v;
return table;
}
@ -46,7 +38,7 @@ namespace BizHawk.Client.Common
public LuaTable ListToTable<T>(IReadOnlyList<T> list, int indexFrom = 1)
{
var table = NewTable();
var table = CreateTable();
for (int i = 0, l = list.Count; i != l; i++) table[indexFrom + i] = list[i];
return table;
}
@ -63,7 +55,7 @@ namespace BizHawk.Client.Common
public LuaTable ObjectToTable(object obj)
{
var table = NewTable();
var table = CreateTable();
foreach (var method in obj.GetType().GetMethods())
{
if (!method.IsPublic) continue;

View File

@ -128,7 +128,7 @@ namespace BizHawk.Client.EmuHawk
private readonly MainForm _mainForm;
private Lua _lua = new() { State = { Encoding = Encoding.UTF8 } };
private Lua _lua = new();
private LuaThread _currThread;
private readonly NLuaTableHelper _th;
@ -141,9 +141,7 @@ namespace BizHawk.Client.EmuHawk
private EmulationLuaLibrary EmulationLuaLibrary => (EmulationLuaLibrary)Libraries[typeof(EmulationLuaLibrary)];
// nb: KeraLua isn't really the engine, NLua does the heavy lifting (KeraLua is just a thin layer for native lua)
// this is just done to differentiate against the old NLua engine, which was backed by KopiLua (c# impl of lua) instead of KeraLua
public string EngineName => "KeraLua";
public string EngineName => "NLua+Lua";
public bool IsRebootingCore { get; set; }
@ -330,8 +328,8 @@ namespace BizHawk.Client.EmuHawk
_currThread = null;
var result = execResult switch
{
KeraLua.LuaStatus.OK => (WaitForFrame: false, Terminated: true),
KeraLua.LuaStatus.Yield => (WaitForFrame: FrameAdvanceRequested, Terminated: false),
LuaStatus.OK => (WaitForFrame: false, Terminated: true),
LuaStatus.Yield => (WaitForFrame: FrameAdvanceRequested, Terminated: false),
_ => throw new InvalidOperationException($"{nameof(_currThread.Resume)}() returned {execResult}?")
};

View File

@ -16,10 +16,9 @@
<PackageReference Include="MSTest.TestFramework" Version="2.2.8" PrivateAssets="all" />
<PackageReference Include="JunitXml.TestLogger" Version="3.0.98" PrivateAssets="all" />
<ProjectReference Include="$(ProjectDir)../BizHawk.Client.Common/BizHawk.Client.Common.csproj" />
<Reference Include="NLua, Version=1.4.1.0, Culture=neutral, PublicKeyToken=null, processorArchitecture=MSIL" SpecificVersion="false" HintPath="$(ProjectDir)../../References/NLua.dll" Private="false" />
<Reference Include="KeraLua, Version=1.3.2.0, Culture=neutral, PublicKeyToken=6a194c04b9c89217, processorArchitecture=MSIL" SpecificVersion="false" HintPath="$(ProjectDir)../../References/KeraLua.dll" Private="false" />
<None Include="$(ProjectDir)../../References/*Lua.dll" CopyToOutputDirectory="PreserveNewest" />
<None Include="$(ProjectDir)../../Assets/dll/*lua54.*" CopyToOutputDirectory="PreserveNewest" />
<Reference Include="NLua, Version=1.4.1.0, Culture=neutral, PublicKeyToken=null, processorArchitecture=MSIL" SpecificVersion="false" HintPath="$(ProjectDir)../../References/NLua.dll" Private="true" />
<None Include="$(ProjectDir)../../Assets/dll/lua54.dll" CopyToOutputDirectory="PreserveNewest" />
<!-- CHECKME: Does liblua5.4.so from a Linux host get picked up correctly? -->
<None Include="$(ProjectDir)../../Assets/dll/libbizhash.*" CopyToOutputDirectory="PreserveNewest" />
<None Include="$(ProjectDir)../../Assets/dll/libzstd.*" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

View File

@ -2,11 +2,8 @@
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using BizHawk.Client.Common;
using BizHawk.Common.StringExtensions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
@ -15,7 +12,7 @@ namespace BizHawk.Tests.Client.Common.Lua
[TestClass]
public class LuaTests
{
private static readonly NLua.Lua LuaInstance = new() { State = { Encoding = Encoding.UTF8 } };
private static readonly NLua.Lua LuaInstance = new();
private static readonly NLuaTableHelper _th = new(LuaInstance, Console.WriteLine);
private static object? ExpectedValue { get; set; }