Improve NLua lua library loading, using C# function pointers. It now no longer depends on BizHawk.BizInvoke/BizHawk.Common. It might be faster too
Add in liblua-* variant for Linux lua library names (resolves #3678) Remove some more unused NLua code Make LuaState internal, we don't need to see it (NLua.Lua API slightly changed to accommodate this, tests could be broken due to this?) Make various other NLua classes internal, we don't need to see them Check against lua library loading failing, provide a non-fatal message box if it has failed instead of crashing on some exception. Remove UnixSearchPaths (unneeded with LD_LIBRARY_PATH being set) and unused IImportResolvers
This commit is contained in:
parent
1956302a15
commit
ba24907d9c
|
@ -21,13 +21,9 @@
|
|||
<WarningsAsErrors />
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="BizHawk.BizInvoke" HintPath="../../output/dll/BizHawk.BizInvoke.dll" />
|
||||
<Reference Include="BizHawk.Common" HintPath="../../output/dll/BizHawk.Common.dll" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<NoWarn>$(NoWarn);IDE0005</NoWarn>
|
||||
<Nullable>disable</Nullable>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
|
@ -198,14 +198,16 @@ namespace NLua
|
|||
return _extractNetObject;
|
||||
case LuaType.Table:
|
||||
{
|
||||
if (luaState.GetMetaField(stackPos, "__index") != LuaType.Nil)
|
||||
if (luaState.GetMetaField(stackPos, "__index") == LuaType.Nil)
|
||||
{
|
||||
var obj = _translator.GetNetObject(luaState, -1);
|
||||
luaState.SetTop(-2);
|
||||
if (obj != null && paramType.IsInstanceOfType(obj))
|
||||
{
|
||||
return _extractNetObject;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
var obj = _translator.GetNetObject(luaState, -1);
|
||||
luaState.SetTop(-2);
|
||||
if (obj != null && paramType.IsInstanceOfType(obj))
|
||||
{
|
||||
return _extractNetObject;
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -219,7 +221,7 @@ namespace NLua
|
|||
case LuaType.UserData:
|
||||
case LuaType.Thread:
|
||||
default:
|
||||
return null;
|
||||
break;
|
||||
}
|
||||
|
||||
var netObj = _translator.GetNetObject(luaState, stackPos);
|
||||
|
|
|
@ -28,12 +28,10 @@ namespace NLua
|
|||
// ReSharper disable once UnusedAutoPropertyAccessor.Global
|
||||
public bool IsExecuting { get; private set; }
|
||||
|
||||
public LuaState State { get; private set; }
|
||||
internal LuaState State { get; private set; }
|
||||
|
||||
internal ObjectTranslator Translator { get; private set; }
|
||||
|
||||
private readonly bool _StatePassed;
|
||||
|
||||
// The commented code bellow is the initLua, the code assigned here is minified for size/performance reasons.
|
||||
private const string InitLuanet = @"local a={}local rawget=rawget;local b=luanet.import_type;local c=luanet.load_assembly;luanet.error,luanet.type=error,type;function a:__index(d)local e=rawget(self,'.fqn')e=(e and e..'.'or'')..d;local f=rawget(luanet,d)or b(e)if f==nil then pcall(c,e)f={['.fqn']=e}setmetatable(f,a)end;rawset(self,d,f)return f end;function a:__call(...)error('No such type: '..rawget(self,'.fqn'),2)end;luanet['.fqn']=false;setmetatable(luanet,a)luanet.load_assembly('mscorlib')";
|
||||
//@"local metatable = {}
|
||||
|
@ -243,34 +241,13 @@ namespace NLua
|
|||
State.AtPanic(_panicCallback);
|
||||
}
|
||||
|
||||
// CAUTION: NLua.Lua instances can't share the same lua state!
|
||||
public Lua(LuaState luaState)
|
||||
{
|
||||
luaState.PushString("NLua_Loaded");
|
||||
luaState.GetTable((int)LuaRegistry.Index);
|
||||
|
||||
if (luaState.ToBoolean(-1))
|
||||
{
|
||||
luaState.SetTop(-2);
|
||||
throw new LuaException("There is already a NLua.Lua instance associated with this Lua state");
|
||||
}
|
||||
|
||||
State = luaState;
|
||||
_StatePassed = true;
|
||||
luaState.SetTop(-2);
|
||||
Init();
|
||||
}
|
||||
|
||||
internal void Init()
|
||||
{
|
||||
State.PushString("NLua_Loaded");
|
||||
State.PushBoolean(true);
|
||||
State.SetTable((int)LuaRegistry.Index);
|
||||
if (_StatePassed == false)
|
||||
{
|
||||
State.NewTable();
|
||||
State.SetGlobal("luanet");
|
||||
}
|
||||
State.NewTable();
|
||||
State.SetGlobal("luanet");
|
||||
State.PushGlobalTable();
|
||||
State.GetGlobal("luanet");
|
||||
State.PushString("getmetatable");
|
||||
|
@ -287,7 +264,7 @@ namespace NLua
|
|||
|
||||
public void Close()
|
||||
{
|
||||
if (_StatePassed || State == null)
|
||||
if (State == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -341,7 +318,7 @@ namespace NLua
|
|||
/// <para>Return a debug.traceback() call result (a multi-line string, containing a full stack trace, including C calls.</para>
|
||||
/// <para>Note: it won't return anything unless the interpreter is in the middle of execution - that is, it only makes sense to call it from a method called from Lua, or during a coroutine yield.</para>
|
||||
/// </summary>
|
||||
public string GetDebugTraceback()
|
||||
internal string GetDebugTraceback()
|
||||
{
|
||||
var oldTop = State.GetTop();
|
||||
State.GetGlobal("debug"); // stack: debug
|
||||
|
@ -875,7 +852,7 @@ namespace NLua
|
|||
State.SetTable(-3);
|
||||
}
|
||||
|
||||
State.SetTop( oldTop);
|
||||
State.SetTop(oldTop);
|
||||
}
|
||||
|
||||
public Dictionary<object, object> GetTableDict(LuaTable table)
|
||||
|
@ -900,41 +877,6 @@ namespace NLua
|
|||
return dict;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets up value (see lua docs)
|
||||
/// </summary>
|
||||
/// <param name = "funcindex">see lua docs</param>
|
||||
/// <param name = "n">see lua docs</param>
|
||||
/// <returns>see lua docs</returns>
|
||||
public string GetUpValue(int funcindex, int n)
|
||||
=> State.GetUpValue(funcindex, n);
|
||||
|
||||
/// <summary>
|
||||
/// Sets up value (see lua docs)
|
||||
/// </summary>
|
||||
/// <param name = "funcindex">see lua docs</param>
|
||||
/// <param name = "n">see lua docs</param>
|
||||
/// <returns>see lua docs</returns>
|
||||
public string SetUpValue(int funcindex, int n)
|
||||
=> State.SetUpValue(funcindex, n);
|
||||
|
||||
/// <summary>
|
||||
/// Pops a value from the lua stack.
|
||||
/// </summary>
|
||||
/// <returns>Returns the top value from the lua stack.</returns>
|
||||
public object Pop()
|
||||
{
|
||||
var top = State.GetTop();
|
||||
return Translator.PopValues(State, top - 1)[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pushes a value onto the lua stack.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to push.</param>
|
||||
public void Push(object value)
|
||||
=> Translator.Push(State, value);
|
||||
|
||||
internal void DisposeInternal(int reference, bool finalized)
|
||||
{
|
||||
if (finalized && Translator != null)
|
||||
|
@ -1028,137 +970,35 @@ namespace NLua
|
|||
return state;
|
||||
}
|
||||
|
||||
public void XMove(LuaState to, object val, int index = 1)
|
||||
{
|
||||
var oldTop = State.GetTop();
|
||||
|
||||
Translator.Push(State, val);
|
||||
State.XMove(to, index);
|
||||
|
||||
State.SetTop(oldTop);
|
||||
}
|
||||
|
||||
public void XMove(Lua to, object val, int index = 1)
|
||||
{
|
||||
var oldTop = State.GetTop();
|
||||
|
||||
Translator.Push(State, val);
|
||||
State.XMove(to.State, index);
|
||||
|
||||
State.SetTop(oldTop);
|
||||
}
|
||||
|
||||
public void XMove(LuaThread thread, object val, int index = 1)
|
||||
{
|
||||
var oldTop = State.GetTop();
|
||||
|
||||
Translator.Push(State, val);
|
||||
State.XMove(thread.State, index);
|
||||
|
||||
State.SetTop(oldTop);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new empty thread
|
||||
/// </summary>
|
||||
public LuaState NewThread(out LuaThread thread)
|
||||
public LuaThread NewThread()
|
||||
{
|
||||
var oldTop = State.GetTop();
|
||||
|
||||
var state = State.NewThread();
|
||||
thread = (LuaThread)Translator.GetObject(State, -1);
|
||||
State.NewThread();
|
||||
var thread = (LuaThread)Translator.GetObject(State, -1);
|
||||
|
||||
State.SetTop(oldTop);
|
||||
return state;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new empty thread as a global variable or as a field
|
||||
/// inside an existing table
|
||||
/// </summary>
|
||||
public LuaState NewThread(string fullPath)
|
||||
{
|
||||
var path = FullPathToArray(fullPath);
|
||||
var oldTop = State.GetTop();
|
||||
|
||||
LuaState state;
|
||||
|
||||
if (path.Length == 1)
|
||||
{
|
||||
state = State.NewThread();
|
||||
State.SetGlobal(fullPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
State.GetGlobal(path[0]);
|
||||
|
||||
for (var i = 1; i < path.Length - 1; i++)
|
||||
{
|
||||
State.PushString(path[i]);
|
||||
State.GetTable(-2);
|
||||
}
|
||||
|
||||
State.PushString(path[path.Length - 1]);
|
||||
state = State.NewThread();
|
||||
State.SetTable(-3);
|
||||
}
|
||||
|
||||
State.SetTop(oldTop);
|
||||
return state;
|
||||
return thread;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new coroutine thread
|
||||
/// </summary>
|
||||
public LuaState NewThread(LuaFunction function, out LuaThread thread)
|
||||
public LuaThread NewThread(LuaFunction function)
|
||||
{
|
||||
var oldTop = State.GetTop();
|
||||
|
||||
var state = State.NewThread();
|
||||
thread = (LuaThread)Translator.GetObject(State, -1);
|
||||
|
||||
Translator.Push(State, function);
|
||||
State.XMove(state, 1);
|
||||
|
||||
State.SetTop(oldTop);
|
||||
return state;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new coroutine thread as a global variable or as a field
|
||||
/// inside an existing table
|
||||
/// </summary>
|
||||
public void NewThread(string fullPath, LuaFunction function)
|
||||
{
|
||||
var path = FullPathToArray(fullPath);
|
||||
var oldTop = State.GetTop();
|
||||
|
||||
LuaState state;
|
||||
|
||||
if (path.Length == 1)
|
||||
{
|
||||
state = State.NewThread();
|
||||
State.SetGlobal(fullPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
State.GetGlobal(path[0]);
|
||||
|
||||
for (var i = 1; i < path.Length - 1; i++)
|
||||
{
|
||||
State.PushString(path[i]);
|
||||
State.GetTable(-2);
|
||||
}
|
||||
|
||||
State.PushString(path[path.Length - 1]);
|
||||
state = State.NewThread();
|
||||
State.SetTable(-3);
|
||||
}
|
||||
var thread = (LuaThread)Translator.GetObject(State, -1);
|
||||
|
||||
Translator.Push(State, function);
|
||||
State.XMove(state, 1);
|
||||
|
||||
State.SetTop(oldTop);
|
||||
return thread;
|
||||
}
|
||||
|
||||
public LuaFunction RegisterFunction(string path, MethodBase function)
|
||||
|
@ -1172,7 +1012,7 @@ namespace NLua
|
|||
{
|
||||
// We leave nothing on the stack when we are done
|
||||
var oldTop = State.GetTop();
|
||||
var wrapper = new LuaMethodWrapper(Translator, target, new ProxyType(function.DeclaringType), function);
|
||||
var wrapper = new LuaMethodWrapper(Translator, target, new(function.DeclaringType), function);
|
||||
|
||||
Translator.Push(State, new LuaNativeFunction(wrapper.InvokeFunction));
|
||||
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace NLua
|
||||
{
|
||||
/// <summary>
|
||||
/// Marks a method for global usage in Lua scripts
|
||||
/// </summary>
|
||||
[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; }
|
||||
}
|
||||
}
|
|
@ -135,18 +135,14 @@ namespace NLua
|
|||
foreach (var method in type.GetMethods(BindingFlags.Public | BindingFlags.Instance))
|
||||
{
|
||||
var 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))
|
||||
// Exclude some generic .NET methods that wouldn't be very useful in Lua
|
||||
if (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
|
||||
var command = path + ":" + name + "(";
|
||||
|
@ -161,23 +157,14 @@ namespace NLua
|
|||
|
||||
foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.Instance))
|
||||
{
|
||||
// Check that the LuaHideAttribute and LuaGlobalAttribute were not applied
|
||||
if (!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);
|
||||
}
|
||||
// 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")
|
||||
// Exclude some generic .NET properties that wouldn't be very useful in Lua
|
||||
if (property.Name != "Item")
|
||||
{
|
||||
// Go into recursion for members
|
||||
RegisterPath(path + "." + property.Name, property.PropertyType, recursionCounter + 1, entry);
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace NLua
|
||||
{
|
||||
/// <summary>
|
||||
/// Marks a method, field or property to be hidden from Lua auto-completion
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property)]
|
||||
public sealed class LuaHideAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
|
@ -6,11 +6,11 @@ using NLua.Native;
|
|||
|
||||
namespace NLua
|
||||
{
|
||||
public class LuaThread : LuaBase, IEquatable<LuaThread>, IEquatable<LuaState>, IEquatable<Lua>
|
||||
public class LuaThread : LuaBase, IEquatable<LuaThread>, IEquatable<Lua>
|
||||
{
|
||||
private readonly ObjectTranslator _translator;
|
||||
|
||||
public LuaState State { get; }
|
||||
internal LuaState State { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the main thread object
|
||||
|
@ -38,6 +38,7 @@ namespace NLua
|
|||
/// <summary>
|
||||
/// Resumes this thread
|
||||
/// </summary>
|
||||
// ReSharper disable once UnusedMember.Global
|
||||
public LuaStatus Resume()
|
||||
{
|
||||
// We leave nothing on the stack if we error
|
||||
|
@ -76,39 +77,10 @@ namespace NLua
|
|||
/// <summary>
|
||||
/// Yields this thread
|
||||
/// </summary>
|
||||
// ReSharper disable once UnusedMember.Global
|
||||
public void Yield()
|
||||
=> State.Yield(0);
|
||||
|
||||
public void XMove(LuaState to, object val, int index = 1)
|
||||
{
|
||||
var oldTop = State.GetTop();
|
||||
|
||||
_translator.Push(State, val);
|
||||
State.XMove(to, index);
|
||||
|
||||
State.SetTop(oldTop);
|
||||
}
|
||||
|
||||
public void XMove(Lua to, object val, int index = 1)
|
||||
{
|
||||
var oldTop = State.GetTop();
|
||||
|
||||
_translator.Push(State, val);
|
||||
State.XMove(to.State, index);
|
||||
|
||||
State.SetTop(oldTop);
|
||||
}
|
||||
|
||||
public void XMove(LuaThread thread, object val, int index = 1)
|
||||
{
|
||||
var oldTop = State.GetTop();
|
||||
|
||||
_translator.Push(State, val);
|
||||
State.XMove(thread.State, index);
|
||||
|
||||
State.SetTop(oldTop);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pushes this thread into the Lua stack
|
||||
/// </summary>
|
||||
|
@ -122,7 +94,6 @@ namespace NLua
|
|||
{
|
||||
LuaThread thread => State == thread.State,
|
||||
Lua interpreter => State == interpreter.State,
|
||||
LuaState state => State == state,
|
||||
_ => base.Equals(obj)
|
||||
};
|
||||
|
||||
|
@ -130,20 +101,13 @@ namespace NLua
|
|||
=> base.GetHashCode();
|
||||
|
||||
public bool Equals(LuaThread other) => State == other?.State;
|
||||
public bool Equals(LuaState other) => State == other;
|
||||
public bool Equals(Lua other) => 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;
|
||||
|
|
|
@ -11,7 +11,7 @@ using NLua.Native;
|
|||
|
||||
namespace NLua
|
||||
{
|
||||
public class MetaFunctions
|
||||
internal class MetaFunctions
|
||||
{
|
||||
public static readonly LuaNativeFunction GcFunction = CollectObject;
|
||||
public static readonly LuaNativeFunction IndexFunction = GetMethod;
|
||||
|
|
|
@ -5,25 +5,7 @@ namespace NLua.Native
|
|||
{
|
||||
internal static class DelegateExtensions
|
||||
{
|
||||
public static LuaNativeFunction ToLuaFunction(this IntPtr ptr)
|
||||
=> ptr == IntPtr.Zero ? null : Marshal.GetDelegateForFunctionPointer<LuaNativeFunction>(ptr);
|
||||
|
||||
public static IntPtr ToFunctionPointer(this LuaNativeFunction d)
|
||||
=> d == null ? IntPtr.Zero : Marshal.GetFunctionPointerForDelegate(d);
|
||||
|
||||
public static IntPtr ToFunctionPointer(this LuaKFunction d)
|
||||
=> d == null ? IntPtr.Zero : Marshal.GetFunctionPointerForDelegate(d);
|
||||
|
||||
public static IntPtr ToFunctionPointer(this LuaReader d)
|
||||
=> d == null ? IntPtr.Zero : Marshal.GetFunctionPointerForDelegate(d);
|
||||
|
||||
public static IntPtr ToFunctionPointer(this LuaWriter d)
|
||||
=> d == null ? IntPtr.Zero : Marshal.GetFunctionPointerForDelegate(d);
|
||||
|
||||
public static LuaAlloc ToLuaAlloc(this IntPtr ptr)
|
||||
=> ptr == IntPtr.Zero ? null : Marshal.GetDelegateForFunctionPointer<LuaAlloc>(ptr);
|
||||
|
||||
public static IntPtr ToFunctionPointer(this LuaAlloc d)
|
||||
=> d == null ? IntPtr.Zero : Marshal.GetFunctionPointerForDelegate(d);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
|
||||
using charptr_t = System.IntPtr;
|
||||
using lua_KContext = System.IntPtr;
|
||||
using lua_State = System.IntPtr;
|
||||
using size_t = System.UIntPtr;
|
||||
using voidptr_t = System.IntPtr;
|
||||
|
||||
namespace NLua.Native
|
||||
{
|
||||
|
@ -18,50 +14,4 @@ namespace NLua.Native
|
|||
[SuppressUnmanagedCodeSecurity]
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate int LuaNativeFunction(lua_State luaState);
|
||||
|
||||
/// <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);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,304 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace NLua.Native
|
||||
{
|
||||
public static class LuaNativeMethodLoader
|
||||
{
|
||||
private interface INativeLibraryLoader
|
||||
{
|
||||
IntPtr LoadNativeLibrary(string path);
|
||||
void FreeNativeLibrary(IntPtr handle);
|
||||
IntPtr LoadFunctionPointer(IntPtr handle, string symbol);
|
||||
}
|
||||
|
||||
private class Win32NativeLibraryLoader : INativeLibraryLoader
|
||||
{
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
|
||||
private static extern IntPtr LoadLibraryW(string lpLibFileName);
|
||||
|
||||
[DllImport("kernel32.dll", ExactSpelling = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static extern bool FreeLibrary(IntPtr hLibModule);
|
||||
|
||||
[DllImport("kernel32.dll", ExactSpelling = true)]
|
||||
private static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
|
||||
|
||||
public IntPtr LoadNativeLibrary(string path) => LoadLibraryW(path);
|
||||
|
||||
public void FreeNativeLibrary(IntPtr handle) => FreeLibrary(handle);
|
||||
|
||||
public IntPtr LoadFunctionPointer(IntPtr handle, string symbol) => GetProcAddress(handle, symbol);
|
||||
}
|
||||
|
||||
private class LinuxNativeLibraryLoader : INativeLibraryLoader
|
||||
{
|
||||
private const int RTLD_NOW = 2;
|
||||
private const int RTLD_GLOBAL = 0x100;
|
||||
|
||||
[DllImport("libdl.so.2")]
|
||||
private static extern IntPtr dlopen(string fileName, int flags);
|
||||
|
||||
[DllImport("libdl.so.2")]
|
||||
private static extern int dlclose(IntPtr handle);
|
||||
|
||||
[DllImport("libdl.so.2")]
|
||||
private static extern IntPtr dlsym(IntPtr handle, string symbol);
|
||||
|
||||
public IntPtr LoadNativeLibrary(string path) => dlopen(path, RTLD_NOW | RTLD_GLOBAL);
|
||||
|
||||
public void FreeNativeLibrary(IntPtr handle) => _ = dlclose(handle);
|
||||
|
||||
public IntPtr LoadFunctionPointer(IntPtr handle, string symbol) => dlsym(handle, symbol);
|
||||
}
|
||||
|
||||
private class LibcNativeLibraryLoader : INativeLibraryLoader
|
||||
{
|
||||
private const int RTLD_NOW = 2;
|
||||
private const int RTLD_GLOBAL = 0x100;
|
||||
|
||||
[DllImport("libc")]
|
||||
private static extern IntPtr dlopen(string fileName, int flags);
|
||||
|
||||
[DllImport("libc")]
|
||||
private static extern int dlclose(IntPtr handle);
|
||||
|
||||
[DllImport("libc")]
|
||||
private static extern IntPtr dlsym(IntPtr handle, string symbol);
|
||||
|
||||
public IntPtr LoadNativeLibrary(string path) => dlopen(path, RTLD_NOW | RTLD_GLOBAL);
|
||||
|
||||
public void FreeNativeLibrary(IntPtr handle) => _ = dlclose(handle);
|
||||
|
||||
public IntPtr LoadFunctionPointer(IntPtr handle, string symbol) => dlsym(handle, symbol);
|
||||
}
|
||||
|
||||
private static INativeLibraryLoader GetNativeLibraryLoader()
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
return new Win32NativeLibraryLoader();
|
||||
}
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
{
|
||||
return new LinuxNativeLibraryLoader();
|
||||
}
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ||
|
||||
RuntimeInformation.OSDescription.ToUpperInvariant().Contains("BSD"))
|
||||
{
|
||||
return new LibcNativeLibraryLoader();
|
||||
}
|
||||
|
||||
throw new NotSupportedException("This OS does not support loading native libraries");
|
||||
}
|
||||
|
||||
private static IEnumerable<string> NativeLuaLibraryPaths()
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
return new[] { "lua54.dll" };
|
||||
}
|
||||
|
||||
// Linux is tricky as we want to use the system lua library
|
||||
// but old (but not yet EOL) distros may not have lua 5.4
|
||||
// we can safely use lua 5.3 for our purposes, hope the
|
||||
// user's distro provides at least lua 5.3!
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ||
|
||||
RuntimeInformation.OSDescription.ToUpperInvariant().Contains("BSD"))
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
"liblua.so.5.4.6", "liblua.so.5.4", "liblua-5.4.so", "liblua5.4.so", "liblua5.4.so.0",
|
||||
"liblua.so.5.3.6", "liblua.so.5.3", "liblua-5.3.so", "liblua5.3.so", "liblua5.3.so.0",
|
||||
};
|
||||
}
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
||||
{
|
||||
return new[] { "liblua54.dylib" };
|
||||
}
|
||||
|
||||
throw new NotSupportedException("This OS does not support loading native lua.");
|
||||
}
|
||||
|
||||
private static unsafe bool LoadNativeLuaMethods(Func<string, IntPtr> loadFunction, LuaNativeMethods nativeMethods)
|
||||
{
|
||||
nativeMethods.lua_atpanic = (delegate* unmanaged[Cdecl]<IntPtr, IntPtr, IntPtr>)loadFunction("lua_atpanic");
|
||||
if (nativeMethods.lua_atpanic == null) return false;
|
||||
nativeMethods.lua_checkstack = (delegate* unmanaged[Cdecl]<IntPtr, int, int>)loadFunction("lua_checkstack");
|
||||
if (nativeMethods.lua_checkstack == null) return false;
|
||||
nativeMethods.lua_close = (delegate* unmanaged[Cdecl]<IntPtr, void>)loadFunction("lua_close");
|
||||
if (nativeMethods.lua_close == null) return false;
|
||||
nativeMethods.lua_compare = (delegate* unmanaged[Cdecl]<IntPtr, int, int, int, int>)loadFunction("lua_compare");
|
||||
if (nativeMethods.lua_compare == null) return false;
|
||||
nativeMethods.lua_createtable = (delegate* unmanaged[Cdecl]<IntPtr, int, int, void>)loadFunction("lua_createtable");
|
||||
if (nativeMethods.lua_createtable == null) return false;
|
||||
nativeMethods.lua_error = (delegate* unmanaged[Cdecl]<IntPtr, int>)loadFunction("lua_error");
|
||||
if (nativeMethods.lua_error == null) return false;
|
||||
nativeMethods.lua_getfield = (delegate* unmanaged[Cdecl]<IntPtr, int, IntPtr, int>)loadFunction("lua_getfield");
|
||||
if (nativeMethods.lua_getfield == null) return false;
|
||||
nativeMethods.lua_getglobal = (delegate* unmanaged[Cdecl]<IntPtr, IntPtr, int>)loadFunction("lua_getglobal");
|
||||
if (nativeMethods.lua_getglobal == null) return false;
|
||||
nativeMethods.lua_getmetatable = (delegate* unmanaged[Cdecl]<IntPtr, int, int>)loadFunction("lua_getmetatable");
|
||||
if (nativeMethods.lua_getmetatable == null) return false;
|
||||
nativeMethods.lua_gettable = (delegate* unmanaged[Cdecl]<IntPtr, int, int>)loadFunction("lua_gettable");
|
||||
if (nativeMethods.lua_gettable == null) return false;
|
||||
nativeMethods.lua_gettop = (delegate* unmanaged[Cdecl]<IntPtr, int>)loadFunction("lua_gettop");
|
||||
if (nativeMethods.lua_gettop == null) return false;
|
||||
nativeMethods.lua_isinteger = (delegate* unmanaged[Cdecl]<IntPtr, int, int>)loadFunction("lua_isinteger");
|
||||
if (nativeMethods.lua_isinteger == null) return false;
|
||||
nativeMethods.lua_isnumber = (delegate* unmanaged[Cdecl]<IntPtr, int, int>)loadFunction("lua_isnumber");
|
||||
if (nativeMethods.lua_isnumber == null) return false;
|
||||
nativeMethods.lua_isstring = (delegate* unmanaged[Cdecl]<IntPtr, int, int>)loadFunction("lua_isstring");
|
||||
if (nativeMethods.lua_isstring == null) return false;
|
||||
nativeMethods.lua_newthread = (delegate* unmanaged[Cdecl]<IntPtr, IntPtr>)loadFunction("lua_newthread");
|
||||
if (nativeMethods.lua_newthread == null) return false;
|
||||
if (nativeMethods.IsLua53)
|
||||
{
|
||||
nativeMethods.lua_newuserdata = (delegate* unmanaged[Cdecl]<IntPtr, UIntPtr, IntPtr>)loadFunction("lua_newuserdata");
|
||||
if (nativeMethods.lua_newuserdata == null) return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
nativeMethods.lua_newuserdatauv = (delegate* unmanaged[Cdecl]<IntPtr, UIntPtr, int, IntPtr>)loadFunction("lua_newuserdatauv");
|
||||
if (nativeMethods.lua_newuserdatauv == null) return false;
|
||||
}
|
||||
nativeMethods.lua_next = (delegate* unmanaged[Cdecl]<IntPtr, int, int>)loadFunction("lua_next");
|
||||
if (nativeMethods.lua_next == null) return false;
|
||||
nativeMethods.lua_pcallk = (delegate* unmanaged[Cdecl]<IntPtr, int, int, int, IntPtr, IntPtr, int>)loadFunction("lua_pcallk");
|
||||
if (nativeMethods.lua_pcallk == null) return false;
|
||||
nativeMethods.lua_pushboolean = (delegate* unmanaged[Cdecl]<IntPtr, int, void>)loadFunction("lua_pushboolean");
|
||||
if (nativeMethods.lua_pushboolean == null) return false;
|
||||
nativeMethods.lua_pushcclosure = (delegate* unmanaged[Cdecl]<IntPtr, IntPtr, int, void>)loadFunction("lua_pushcclosure");
|
||||
if (nativeMethods.lua_pushcclosure == null) return false;
|
||||
nativeMethods.lua_pushinteger = (delegate* unmanaged[Cdecl]<IntPtr, long, void>)loadFunction("lua_pushinteger");
|
||||
if (nativeMethods.lua_pushinteger == null) return false;
|
||||
nativeMethods.lua_pushlightuserdata = (delegate* unmanaged[Cdecl]<IntPtr, IntPtr, void>)loadFunction("lua_pushlightuserdata");
|
||||
if (nativeMethods.lua_pushlightuserdata == null) return false;
|
||||
nativeMethods.lua_pushlstring = (delegate* unmanaged[Cdecl]<IntPtr, IntPtr, UIntPtr, IntPtr>)loadFunction("lua_pushlstring");
|
||||
if (nativeMethods.lua_pushlstring == null) return false;
|
||||
nativeMethods.lua_pushnil = (delegate* unmanaged[Cdecl]<IntPtr, void>)loadFunction("lua_pushnil");
|
||||
if (nativeMethods.lua_pushnil == null) return false;
|
||||
nativeMethods.lua_pushnumber = (delegate* unmanaged[Cdecl]<IntPtr, double, void>)loadFunction("lua_pushnumber");
|
||||
if (nativeMethods.lua_pushnumber == null) return false;
|
||||
nativeMethods.lua_pushthread = (delegate* unmanaged[Cdecl]<IntPtr, int>)loadFunction("lua_pushthread");
|
||||
if (nativeMethods.lua_pushthread == null) return false;
|
||||
nativeMethods.lua_pushvalue = (delegate* unmanaged[Cdecl]<IntPtr, int, void>)loadFunction("lua_pushvalue");
|
||||
if (nativeMethods.lua_pushvalue == null) return false;
|
||||
nativeMethods.lua_rawequal = (delegate* unmanaged[Cdecl]<IntPtr, int, int, int>)loadFunction("lua_rawequal");
|
||||
if (nativeMethods.lua_rawequal == null) return false;
|
||||
nativeMethods.lua_rawget = (delegate* unmanaged[Cdecl]<IntPtr, int, int>)loadFunction("lua_rawget");
|
||||
if (nativeMethods.lua_rawget == null) return false;
|
||||
nativeMethods.lua_rawgeti = (delegate* unmanaged[Cdecl]<IntPtr, int, long, int>)loadFunction("lua_rawgeti");
|
||||
if (nativeMethods.lua_rawgeti == null) return false;
|
||||
nativeMethods.lua_rawset = (delegate* unmanaged[Cdecl]<IntPtr, int, void>)loadFunction("lua_rawset");
|
||||
if (nativeMethods.lua_rawset == null) return false;
|
||||
nativeMethods.lua_rawseti = (delegate* unmanaged[Cdecl]<IntPtr, int, long, void>)loadFunction("lua_rawseti");
|
||||
if (nativeMethods.lua_rawseti == null) return false;
|
||||
if (nativeMethods.IsLua53)
|
||||
{
|
||||
nativeMethods.lua_resume_53 = (delegate* unmanaged[Cdecl]<IntPtr, IntPtr, int, int>)loadFunction("lua_resume");
|
||||
if (nativeMethods.lua_resume_53 == null) return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
nativeMethods.lua_resume_54 = (delegate* unmanaged[Cdecl]<IntPtr, IntPtr, int, out int, int>)loadFunction("lua_resume");
|
||||
if (nativeMethods.lua_resume_54 == null) return false;
|
||||
}
|
||||
nativeMethods.lua_rotate = (delegate* unmanaged[Cdecl]<IntPtr, int, int, void>)loadFunction("lua_rotate");
|
||||
if (nativeMethods.lua_rotate == null) return false;
|
||||
nativeMethods.lua_setglobal = (delegate* unmanaged[Cdecl]<IntPtr, IntPtr, void>)loadFunction("lua_setglobal");
|
||||
if (nativeMethods.lua_setglobal == null) return false;
|
||||
nativeMethods.lua_setmetatable = (delegate* unmanaged[Cdecl]<IntPtr, int, void>)loadFunction("lua_setmetatable");
|
||||
if (nativeMethods.lua_setmetatable == null) return false;
|
||||
nativeMethods.lua_settable = (delegate* unmanaged[Cdecl]<IntPtr, int, void>)loadFunction("lua_settable");
|
||||
if (nativeMethods.lua_settable == null) return false;
|
||||
nativeMethods.lua_settop = (delegate* unmanaged[Cdecl]<IntPtr, int, void>)loadFunction("lua_settop");
|
||||
if (nativeMethods.lua_settop == null) return false;
|
||||
nativeMethods.lua_toboolean = (delegate* unmanaged[Cdecl]<IntPtr, int, int>)loadFunction("lua_toboolean");
|
||||
if (nativeMethods.lua_toboolean == null) return false;
|
||||
nativeMethods.lua_tointegerx = (delegate* unmanaged[Cdecl]<IntPtr, int, out int, long>)loadFunction("lua_tointegerx");
|
||||
if (nativeMethods.lua_tointegerx == null) return false;
|
||||
nativeMethods.lua_tolstring = (delegate* unmanaged[Cdecl]<IntPtr, int, out UIntPtr, IntPtr>)loadFunction("lua_tolstring");
|
||||
if (nativeMethods.lua_tolstring == null) return false;
|
||||
nativeMethods.lua_tonumberx = (delegate* unmanaged[Cdecl]<IntPtr, int, out int, double>)loadFunction("lua_tonumberx");
|
||||
if (nativeMethods.lua_tonumberx == null) return false;
|
||||
nativeMethods.lua_tothread = (delegate* unmanaged[Cdecl]<IntPtr, int, IntPtr>)loadFunction("lua_tothread");
|
||||
if (nativeMethods.lua_tothread == null) return false;
|
||||
nativeMethods.lua_touserdata = (delegate* unmanaged[Cdecl]<IntPtr, int, IntPtr>)loadFunction("lua_touserdata");
|
||||
if (nativeMethods.lua_touserdata == null) return false;
|
||||
nativeMethods.lua_type = (delegate* unmanaged[Cdecl]<IntPtr, int, int>)loadFunction("lua_type");
|
||||
if (nativeMethods.lua_type == null) return false;
|
||||
nativeMethods.lua_xmove = (delegate* unmanaged[Cdecl]<IntPtr, IntPtr, int, void>)loadFunction("lua_xmove");
|
||||
if (nativeMethods.lua_xmove == null) return false;
|
||||
nativeMethods.lua_yieldk = (delegate* unmanaged[Cdecl]<IntPtr, int, IntPtr, IntPtr, int>)loadFunction("lua_yieldk");
|
||||
if (nativeMethods.lua_yieldk == null) return false;
|
||||
nativeMethods.luaL_getmetafield = (delegate* unmanaged[Cdecl]<IntPtr, int, IntPtr, int>)loadFunction("luaL_getmetafield");
|
||||
if (nativeMethods.luaL_getmetafield == null) return false;
|
||||
nativeMethods.luaL_loadbufferx = (delegate* unmanaged[Cdecl]<IntPtr, IntPtr, UIntPtr, IntPtr, IntPtr, int>)loadFunction("luaL_loadbufferx");
|
||||
if (nativeMethods.luaL_loadbufferx == null) return false;
|
||||
nativeMethods.luaL_loadfilex = (delegate* unmanaged[Cdecl]<IntPtr, IntPtr, IntPtr, int>)loadFunction("luaL_loadfilex");
|
||||
if (nativeMethods.luaL_loadfilex == null) return false;
|
||||
nativeMethods.luaL_newmetatable = (delegate* unmanaged[Cdecl]<IntPtr, IntPtr, int>)loadFunction("luaL_newmetatable");
|
||||
if (nativeMethods.luaL_newmetatable == null) return false;
|
||||
nativeMethods.luaL_newstate = (delegate* unmanaged[Cdecl]<IntPtr>)loadFunction("luaL_newstate");
|
||||
if (nativeMethods.luaL_newstate == null) return false;
|
||||
nativeMethods.luaL_openlibs = (delegate* unmanaged[Cdecl]<IntPtr, void>)loadFunction("luaL_openlibs");
|
||||
if (nativeMethods.luaL_openlibs == null) return false;
|
||||
nativeMethods.luaL_ref = (delegate* unmanaged[Cdecl]<IntPtr, int, int>)loadFunction("luaL_ref");
|
||||
if (nativeMethods.luaL_ref == null) return false;
|
||||
nativeMethods.luaL_tolstring = (delegate* unmanaged[Cdecl]<IntPtr, int, out UIntPtr, IntPtr>)loadFunction("luaL_tolstring");
|
||||
if (nativeMethods.luaL_tolstring == null) return false;
|
||||
nativeMethods.luaL_unref = (delegate* unmanaged[Cdecl]<IntPtr, int, int, void>)loadFunction("luaL_unref");
|
||||
if (nativeMethods.luaL_unref == null) return false;
|
||||
nativeMethods.luaL_where = (delegate* unmanaged[Cdecl]<IntPtr, int, void>)loadFunction("luaL_where");
|
||||
// ReSharper disable once ConvertIfStatementToReturnStatement
|
||||
if (nativeMethods.luaL_where == null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static readonly Lazy<LuaNativeMethods> _nativeMethods = new(() =>
|
||||
{
|
||||
var nativeLibraryLoader = GetNativeLibraryLoader();
|
||||
foreach (var path in NativeLuaLibraryPaths())
|
||||
{
|
||||
var handle = nativeLibraryLoader.LoadNativeLibrary(path);
|
||||
if (handle == IntPtr.Zero)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var nativeMethods = new LuaNativeMethods { IsLua53 = path.IndexOf("5.3", StringComparison.Ordinal) != -1 };
|
||||
if (!LoadNativeLuaMethods(sym => nativeLibraryLoader.LoadFunctionPointer(handle, sym), nativeMethods))
|
||||
{
|
||||
nativeLibraryLoader.FreeNativeLibrary(handle);
|
||||
continue;
|
||||
}
|
||||
|
||||
return nativeMethods;
|
||||
}
|
||||
|
||||
throw new("Could not load native lua methods");
|
||||
});
|
||||
|
||||
internal static LuaNativeMethods GetNativeMethods()
|
||||
=> _nativeMethods.Value;
|
||||
|
||||
public static bool EnsureNativeMethodsLoaded()
|
||||
{
|
||||
try
|
||||
{
|
||||
_ = GetNativeMethods();
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,403 +1,434 @@
|
|||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
|
||||
using BizHawk.BizInvoke;
|
||||
using System.Text;
|
||||
|
||||
using charptr_t = System.IntPtr;
|
||||
using lua_Alloc = System.IntPtr;
|
||||
using lua_CFunction = System.IntPtr;
|
||||
using lua_Integer = System.Int64;
|
||||
using lua_KContext = System.IntPtr;
|
||||
using lua_KFunction = System.IntPtr;
|
||||
using lua_Number = System.Double;
|
||||
using lua_Reader = System.IntPtr;
|
||||
using lua_State = System.IntPtr;
|
||||
using lua_Writer = System.IntPtr;
|
||||
using size_t = System.UIntPtr;
|
||||
using voidptr_t = System.IntPtr;
|
||||
|
||||
#pragma warning disable SA1121 // Use built-in type alias
|
||||
#pragma warning disable IDE1006 // Naming rule violation
|
||||
|
||||
namespace NLua.Native
|
||||
{
|
||||
[SuppressUnmanagedCodeSecurity]
|
||||
public abstract class LuaNativeMethods
|
||||
internal unsafe class LuaNativeMethods
|
||||
{
|
||||
protected const CallingConvention cc = CallingConvention.Cdecl;
|
||||
// TODO: Get rid of this once we're .NET Core/.NET
|
||||
private static class Mershul
|
||||
{
|
||||
public static charptr_t StringToCoTaskMemUTF8(string s)
|
||||
{
|
||||
if (s == null)
|
||||
{
|
||||
return charptr_t.Zero;
|
||||
}
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int lua_absindex(lua_State luaState, int idx);
|
||||
var nb = Encoding.UTF8.GetMaxByteCount(s.Length);
|
||||
var ptr = Marshal.AllocCoTaskMem(checked(nb + 1));
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void lua_arith(lua_State luaState, int op);
|
||||
fixed (char* c = s)
|
||||
{
|
||||
var pbMem = (byte*)ptr;
|
||||
var nbWritten = Encoding.UTF8.GetBytes(c, s.Length, pbMem!, nb);
|
||||
pbMem[nbWritten] = 0;
|
||||
}
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract lua_CFunction lua_atpanic(lua_State luaState, lua_CFunction panicf);
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void lua_callk(lua_State luaState, int nargs, int nresults, lua_KContext ctx, lua_KFunction k);
|
||||
internal bool IsLua53;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int lua_checkstack(lua_State luaState, int extra);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, lua_CFunction, lua_CFunction> lua_atpanic;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void lua_close(lua_State luaState);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public lua_CFunction AtPanic(lua_State luaState, lua_CFunction panicf) => lua_atpanic(luaState, panicf);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int lua_compare(lua_State luaState, int index1, int index2, int op);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, int> lua_checkstack;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void lua_concat(lua_State luaState, int n);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int CheckStack(lua_State luaState, int extra) => lua_checkstack(luaState, extra);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void lua_copy(lua_State luaState, int fromIndex, int toIndex);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, void> lua_close;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void lua_createtable(lua_State luaState, int elements, int records);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Close(lua_State luaState) => lua_close(luaState);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int lua_dump(lua_State luaState, lua_Writer writer, voidptr_t data, int strip);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, int, int, int> lua_compare;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int lua_error(lua_State luaState);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int Compare(lua_State luaState, int index1, int index2, int op) => lua_compare(luaState, index1, index2, op);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract lua_Alloc lua_getallocf(lua_State luaState, ref voidptr_t ud);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, int, void> lua_createtable;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int lua_getfield(lua_State luaState, int index, string k);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void CreateTable(lua_State luaState, int elements, int records) => lua_createtable(luaState, elements, records);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int lua_getglobal(lua_State luaState, string name);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int> lua_error;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int lua_geti(lua_State luaState, int index, long i);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int Error(lua_State luaState) => lua_error(luaState);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int lua_getmetatable(lua_State luaState, int index);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, charptr_t, int> lua_getfield;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int lua_gettable(lua_State luaState, int index);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int GetField(lua_State luaState, int index, string k)
|
||||
{
|
||||
var _k = Mershul.StringToCoTaskMemUTF8(k);
|
||||
try
|
||||
{
|
||||
return lua_getfield(luaState, index, _k);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeCoTaskMem(_k);
|
||||
}
|
||||
}
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int lua_gettop(lua_State luaState);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, charptr_t, int> lua_getglobal;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract charptr_t lua_getupvalue(lua_State luaState, int funcIndex, int n);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int GetGlobal(lua_State luaState, string name)
|
||||
{
|
||||
var _name = Mershul.StringToCoTaskMemUTF8(name);
|
||||
try
|
||||
{
|
||||
return lua_getglobal(luaState, _name);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeCoTaskMem(_name);
|
||||
}
|
||||
}
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int lua_iscfunction(lua_State luaState, int index);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, int> lua_getmetatable;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int lua_isinteger(lua_State luaState, int index);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int GetMetaTable(lua_State luaState, int index) => lua_getmetatable(luaState, index);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int lua_isnumber(lua_State luaState, int index);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, int> lua_gettable;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int lua_isstring(lua_State luaState, int index);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int GetTable(lua_State luaState, int index) => lua_gettable(luaState, index);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int lua_isuserdata(lua_State luaState, int index);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int> lua_gettop;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int lua_isyieldable(lua_State luaState);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int GetTop(lua_State luaState) => lua_gettop(luaState);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void lua_len(lua_State luaState, int index);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, int> lua_isinteger;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int lua_load
|
||||
(lua_State luaState,
|
||||
lua_Reader reader,
|
||||
voidptr_t data,
|
||||
string chunkName,
|
||||
string mode);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int IsInteger(lua_State luaState, int index) => lua_isinteger(luaState, index);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract lua_State lua_newstate(lua_Alloc allocFunction, voidptr_t ud);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, int> lua_isnumber;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract lua_State lua_newthread(lua_State luaState);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int IsNumber(lua_State luaState, int index) => lua_isnumber(luaState, index);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int lua_next(lua_State luaState, int index);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, int> lua_isstring;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int lua_pcallk
|
||||
(lua_State luaState,
|
||||
int nargs,
|
||||
int nresults,
|
||||
int errorfunc,
|
||||
lua_KContext ctx,
|
||||
lua_KFunction k);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int IsString(lua_State luaState, int index) => lua_isstring(luaState, index);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void lua_pushboolean(lua_State luaState, int value);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, lua_State> lua_newthread;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void lua_pushcclosure(lua_State luaState, lua_CFunction f, int n);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public lua_State NewThread(lua_State luaState) => lua_newthread(luaState);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void lua_pushinteger(lua_State luaState, lua_Integer n);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, size_t, int, voidptr_t> lua_newuserdatauv;
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, size_t, voidptr_t> lua_newuserdata;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void lua_pushlightuserdata(lua_State luaState, voidptr_t udata);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public voidptr_t NewUserData(lua_State luaState, size_t size) => lua_newuserdatauv != null
|
||||
? lua_newuserdatauv(luaState, size, 1)
|
||||
: lua_newuserdata(luaState, size);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract charptr_t lua_pushlstring(lua_State luaState, byte[] s, size_t len);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, int> lua_next;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void lua_pushnil(lua_State luaState);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int Next(lua_State luaState, int index) => lua_next(luaState, index);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void lua_pushnumber(lua_State luaState, lua_Number number);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, int, int, lua_KContext, lua_KFunction, int> lua_pcallk;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int lua_pushthread(lua_State luaState);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int PCallK(lua_State luaState, int nargs, int nresults, int errorfunc, lua_KContext ctx, lua_KFunction k) => lua_pcallk(luaState, nargs, nresults, errorfunc, ctx, k);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void lua_pushvalue(lua_State luaState, int index);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, void> lua_pushboolean;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int lua_rawequal(lua_State luaState, int index1, int index2);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void PushBoolean(lua_State luaState, int value) => lua_pushboolean(luaState, value);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int lua_rawget(lua_State luaState, int index);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, lua_CFunction, int, void> lua_pushcclosure;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int lua_rawgeti(lua_State luaState, int index, lua_Integer n);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void PushCClosure(lua_State luaState, lua_CFunction f, int n) => lua_pushcclosure(luaState, f, n);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int lua_rawgetp(lua_State luaState, int index, voidptr_t p);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, lua_Integer, void> lua_pushinteger;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract size_t lua_rawlen(lua_State luaState, int index);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void PushInteger(lua_State luaState, lua_Integer n) => lua_pushinteger(luaState, n);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void lua_rawset(lua_State luaState, int index);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, voidptr_t, void> lua_pushlightuserdata;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void lua_rawseti(lua_State luaState, int index, lua_Integer i);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void PushLightUserData(lua_State luaState, voidptr_t udata) => lua_pushlightuserdata(luaState, udata);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void lua_rawsetp(lua_State luaState, int index, voidptr_t p);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, charptr_t, size_t, charptr_t> lua_pushlstring;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void lua_rotate(lua_State luaState, int index, int n);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public charptr_t PushLString(lua_State luaState, byte[] s, size_t len)
|
||||
{
|
||||
fixed (byte* _s = s)
|
||||
{
|
||||
return lua_pushlstring(luaState, (charptr_t)_s, len);
|
||||
}
|
||||
}
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void lua_setallocf(lua_State luaState, lua_Alloc f, voidptr_t ud);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, void> lua_pushnil;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void lua_setfield(lua_State luaState, int index, string key);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void PushNil(lua_State luaState) => lua_pushnil(luaState);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void lua_setglobal(lua_State luaState, string key);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, lua_Number, void> lua_pushnumber;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void lua_seti(lua_State luaState, int index, long n);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void PushNumber(lua_State luaState, lua_Number number) => lua_pushnumber(luaState, number);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void lua_setmetatable(lua_State luaState, int objIndex);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int> lua_pushthread;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void lua_settable(lua_State luaState, int index);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int PushThread(lua_State luaState) => lua_pushthread(luaState);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void lua_settop(lua_State luaState, int newTop);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, void> lua_pushvalue;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract charptr_t lua_setupvalue(lua_State luaState, int funcIndex, int n);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void PushValue(lua_State luaState, int index) => lua_pushvalue(luaState, index);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int lua_status(lua_State luaState);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, int, int> lua_rawequal;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract size_t lua_stringtonumber(lua_State luaState, string s);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int RawEqual(lua_State luaState, int index1, int index2) => lua_rawequal(luaState, index1, index2);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int lua_toboolean(lua_State luaState, int index);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, int> lua_rawget;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract lua_CFunction lua_tocfunction(lua_State luaState, int index);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int RawGet(lua_State luaState, int index) => lua_rawget(luaState, index);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract lua_Integer lua_tointegerx(lua_State luaState, int index, out int isNum);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, lua_Integer, int> lua_rawgeti;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract charptr_t lua_tolstring(lua_State luaState, int index, out size_t strLen);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int RawGetI(lua_State luaState, int index, lua_Integer n) => lua_rawgeti(luaState, index, n);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract lua_Number lua_tonumberx(lua_State luaState, int index, out int isNum);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, void> lua_rawset;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract voidptr_t lua_topointer(lua_State luaState, int index);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void RawSet(lua_State luaState, int index) => lua_rawset(luaState, index);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract lua_State lua_tothread(lua_State luaState, int index);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, lua_Integer, void> lua_rawseti;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract voidptr_t lua_touserdata(lua_State luaState, int index);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void RawSetI(lua_State luaState, int index, lua_Integer i) => lua_rawseti(luaState, index, i);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int lua_type(lua_State luaState, int index);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, lua_State, int, out int, int> lua_resume_54;
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, lua_State, int, int> lua_resume_53;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract charptr_t lua_typename(lua_State luaState, int type);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int Resume(lua_State luaState, lua_State from, int nargs) => lua_resume_54 != null
|
||||
? lua_resume_54(luaState, from, nargs, out _)
|
||||
: lua_resume_53(luaState, from, nargs);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract voidptr_t lua_upvalueid(lua_State luaState, int funcIndex, int n);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, int, void> lua_rotate;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void lua_upvaluejoin(lua_State luaState, int funcIndex1, int n1, int funcIndex2, int n2);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Rotate(lua_State luaState, int index, int n) => lua_rotate(luaState, index, n);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void lua_xmove(lua_State from, lua_State to, int n);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, charptr_t, void> lua_setglobal;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int lua_yieldk(lua_State luaState,
|
||||
int nresults,
|
||||
lua_KContext ctx,
|
||||
lua_KFunction k);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void SetGlobal(lua_State luaState, string key)
|
||||
{
|
||||
var _key = Mershul.StringToCoTaskMemUTF8(key);
|
||||
try
|
||||
{
|
||||
lua_setglobal(luaState, _key);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeCoTaskMem(_key);
|
||||
}
|
||||
}
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int luaL_argerror(lua_State luaState, int arg, string message);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, void> lua_setmetatable;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int luaL_callmeta(lua_State luaState, int obj, string e);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void SetMetaTable(lua_State luaState, int objIndex) => lua_setmetatable(luaState, objIndex);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void luaL_checkany(lua_State luaState, int arg);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, void> lua_settable;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract lua_Integer luaL_checkinteger(lua_State luaState, int arg);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void SetTable(lua_State luaState, int index) => lua_settable(luaState, index);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract charptr_t luaL_checklstring(lua_State luaState, int arg, out size_t len);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, void> lua_settop;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract lua_Number luaL_checknumber(lua_State luaState, int arg);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void SetTop(lua_State luaState, int newTop) => lua_settop(luaState, newTop);
|
||||
|
||||
[BizImport(cc, Compatibility = true)]
|
||||
public abstract int luaL_checkoption(lua_State luaState, int arg, string def, string[] list);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, int> lua_toboolean;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void luaL_checkstack(lua_State luaState, int sz, string message);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int ToBoolean(lua_State luaState, int index) => lua_toboolean(luaState, index);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void luaL_checktype(lua_State luaState, int arg, int type);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, out int, lua_Integer> lua_tointegerx;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract voidptr_t luaL_checkudata(lua_State luaState, int arg, string tName);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public lua_Integer ToIntegerX(lua_State luaState, int index, out int isNum) => lua_tointegerx(luaState, index, out isNum);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void luaL_checkversion_(lua_State luaState, lua_Number ver, size_t sz);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, out size_t, charptr_t> lua_tolstring;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int luaL_error(lua_State luaState, string message);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public charptr_t ToLString(lua_State luaState, int index, out size_t strLen) => lua_tolstring(luaState, index, out strLen);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int luaL_execresult(lua_State luaState, int stat);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, out int, lua_Number> lua_tonumberx;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int luaL_fileresult(lua_State luaState, int stat, string fileName);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public lua_Number ToNumberX(lua_State luaState, int index, out int isNum) => lua_tonumberx(luaState, index, out isNum);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int luaL_getmetafield(lua_State luaState, int obj, string e);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, lua_State> lua_tothread;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int luaL_getsubtable(lua_State luaState, int index, string name);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public lua_State ToThread(lua_State luaState, int index) => lua_tothread(luaState, index);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract lua_Integer luaL_len(lua_State luaState, int index);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, voidptr_t> lua_touserdata;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int luaL_loadbufferx
|
||||
(lua_State luaState,
|
||||
byte[] buff,
|
||||
size_t sz,
|
||||
string name,
|
||||
string mode);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public voidptr_t ToUserData(lua_State luaState, int index) => lua_touserdata(luaState, index);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int luaL_loadfilex(lua_State luaState, string name, string mode);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, int> lua_type;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int luaL_newmetatable(lua_State luaState, string name);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int Type(lua_State luaState, int index) => lua_type(luaState, index);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract lua_State luaL_newstate();
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, lua_State, int, void> lua_xmove;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void luaL_openlibs(lua_State luaState);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void XMove(lua_State from, lua_State to, int n) => lua_xmove(from, to, n);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract lua_Integer luaL_optinteger(lua_State luaState, int arg, lua_Integer d);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, lua_KContext, lua_KFunction, int> lua_yieldk;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract lua_Number luaL_optnumber(lua_State luaState, int arg, lua_Number d);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int YieldK(lua_State luaState, int nresults, lua_KContext ctx, lua_KFunction k) => lua_yieldk(luaState, nresults, ctx, k);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int luaL_ref(lua_State luaState, int registryIndex);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, charptr_t, int> luaL_getmetafield;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void luaL_requiref(lua_State luaState, string moduleName, lua_CFunction openFunction, int global);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int LGetMetaField(lua_State luaState, int obj, string e)
|
||||
{
|
||||
var _e = Mershul.StringToCoTaskMemUTF8(e);
|
||||
try
|
||||
{
|
||||
return luaL_getmetafield(luaState, obj, _e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeCoTaskMem(_e);
|
||||
}
|
||||
}
|
||||
|
||||
[BizImport(cc, Compatibility = true)]
|
||||
public abstract void luaL_setfuncs(lua_State luaState, [In] LuaRegister[] luaReg, int numUp);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, charptr_t, size_t, charptr_t, charptr_t, int> luaL_loadbufferx;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void luaL_setmetatable(lua_State luaState, string tName);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int LLoadBufferX(lua_State luaState, byte[] buff, size_t sz, string name, string mode)
|
||||
{
|
||||
fixed (byte* _buff = buff)
|
||||
{
|
||||
var _name = charptr_t.Zero;
|
||||
var _mode = charptr_t.Zero;
|
||||
try
|
||||
{
|
||||
_name = Mershul.StringToCoTaskMemUTF8(name);
|
||||
_mode = Mershul.StringToCoTaskMemUTF8(mode);
|
||||
return luaL_loadbufferx(luaState, (charptr_t)_buff, sz, _name, _mode);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeCoTaskMem(_name);
|
||||
Marshal.FreeCoTaskMem(_mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract voidptr_t luaL_testudata(lua_State luaState, int arg, string tName);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, charptr_t, charptr_t, int> luaL_loadfilex;
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract charptr_t luaL_tolstring(lua_State luaState, int index, out size_t len);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int LLoadFileX(lua_State luaState, string name, string mode)
|
||||
{
|
||||
var _name = charptr_t.Zero;
|
||||
var _mode = charptr_t.Zero;
|
||||
try
|
||||
{
|
||||
_name = Mershul.StringToCoTaskMemUTF8(name);
|
||||
_mode = Mershul.StringToCoTaskMemUTF8(mode);
|
||||
return luaL_loadfilex(luaState, _name, _mode);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeCoTaskMem(_name);
|
||||
Marshal.FreeCoTaskMem(_mode);
|
||||
}
|
||||
}
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract charptr_t luaL_traceback
|
||||
(lua_State luaState,
|
||||
lua_State luaState2,
|
||||
string message,
|
||||
int level);
|
||||
|
||||
[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);
|
||||
}
|
||||
|
||||
public abstract class Lua54NativeMethods : LuaNativeMethods
|
||||
{
|
||||
[BizImport(cc)]
|
||||
public abstract int lua_resume(lua_State luaState, lua_State from, int nargs, out int results);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract voidptr_t lua_newuserdatauv(lua_State luaState, size_t size, int nuvalue);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void lua_setiuservalue(lua_State luaState, int index, int n);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int lua_getiuservalue(lua_State luaState, int idx, int n);
|
||||
}
|
||||
|
||||
public abstract class Lua53NativeMethods : LuaNativeMethods
|
||||
{
|
||||
[BizImport(cc)]
|
||||
public abstract int lua_resume(lua_State luaState, lua_State from, int nargs);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract voidptr_t lua_newuserdata(lua_State luaState, size_t size);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract void lua_setuservalue(lua_State luaState, int index);
|
||||
|
||||
[BizImport(cc)]
|
||||
public abstract int lua_getuservalue(lua_State luaState, int idx);
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, charptr_t, int> luaL_newmetatable;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int LNewMetaTable(lua_State luaState, string name)
|
||||
{
|
||||
var _name = Mershul.StringToCoTaskMemUTF8(name);
|
||||
try
|
||||
{
|
||||
return luaL_newmetatable(luaState, _name);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeCoTaskMem(_name);
|
||||
}
|
||||
}
|
||||
|
||||
internal delegate* unmanaged[Cdecl]<lua_State> luaL_newstate;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public lua_State LNewState() => luaL_newstate();
|
||||
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, void> luaL_openlibs;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void LOpenLibs(lua_State luaState) => luaL_openlibs(luaState);
|
||||
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, int> luaL_ref;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int LRef(lua_State luaState, int registryIndex) => luaL_ref(luaState, registryIndex);
|
||||
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, out size_t, charptr_t> luaL_tolstring;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public charptr_t LToLString(lua_State luaState, int index, out size_t len) => luaL_tolstring(luaState, index, out len);
|
||||
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, int, void> luaL_unref;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void LUnref(lua_State luaState, int registryIndex, int reference) => luaL_unref(luaState, registryIndex, reference);
|
||||
|
||||
internal delegate* unmanaged[Cdecl]<lua_State, int, void> luaL_where;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void LWhere(lua_State luaState, int level) => luaL_where(luaState, level);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,67 +0,0 @@
|
|||
namespace NLua.Native
|
||||
{
|
||||
/// <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,
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace NLua.Native
|
||||
{
|
||||
/// <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;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -14,7 +14,7 @@ using NLua.Native;
|
|||
|
||||
namespace NLua
|
||||
{
|
||||
public class ObjectTranslator
|
||||
internal class ObjectTranslator
|
||||
{
|
||||
// Compare cache entries by exact reference to avoid unwanted aliases
|
||||
private class ReferenceComparer : IEqualityComparer<object>
|
||||
|
@ -61,7 +61,7 @@ namespace NLua
|
|||
/// </summary>
|
||||
internal int _nextObj;
|
||||
|
||||
public MetaFunctions MetaFunctionsInstance => metaFunctions;
|
||||
internal MetaFunctions MetaFunctionsInstance => metaFunctions;
|
||||
public Lua Interpreter => interpreter;
|
||||
public IntPtr Tag => _tagPtr;
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ using System.Reflection;
|
|||
|
||||
namespace NLua
|
||||
{
|
||||
public class ProxyType
|
||||
internal class ProxyType
|
||||
{
|
||||
public ProxyType(Type proxy)
|
||||
{
|
||||
|
|
|
@ -14,9 +14,7 @@
|
|||
"Meziantou.Analyzer": "2.0.33",
|
||||
"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"
|
||||
"StyleCop.Analyzers": "1.2.0-beta.435"
|
||||
},
|
||||
"runtime": {
|
||||
"NLua.dll": {}
|
||||
|
@ -42,55 +40,7 @@
|
|||
"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.2": {
|
||||
"runtime": {
|
||||
"System.Memory.dll": {
|
||||
"assemblyVersion": "4.0.1.2",
|
||||
"fileVersion": "4.6.31308.1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"System.Buffers/4.0.3.0": {
|
||||
"runtime": {
|
||||
"System.Buffers.dll": {
|
||||
"assemblyVersion": "4.0.3.0",
|
||||
"fileVersion": "4.6.28619.1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"System.Runtime.CompilerServices.Unsafe/6.0.0.0": {
|
||||
"runtime": {
|
||||
"System.Runtime.CompilerServices.Unsafe.dll": {
|
||||
"assemblyVersion": "6.0.0.0",
|
||||
"fileVersion": "6.0.21.52210"
|
||||
}
|
||||
}
|
||||
},
|
||||
"System.Numerics.Vectors/4.1.4.0": {
|
||||
"runtime": {
|
||||
"System.Numerics.Vectors.dll": {
|
||||
"assemblyVersion": "4.1.4.0",
|
||||
"fileVersion": "4.6.26515.6"
|
||||
}
|
||||
}
|
||||
}
|
||||
"StyleCop.Analyzers.Unstable/1.2.0.435": {}
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
|
@ -161,36 +111,6 @@
|
|||
"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.2": {
|
||||
"type": "reference",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"System.Buffers/4.0.3.0": {
|
||||
"type": "reference",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"System.Runtime.CompilerServices.Unsafe/6.0.0.0": {
|
||||
"type": "reference",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
},
|
||||
"System.Numerics.Vectors/4.1.4.0": {
|
||||
"type": "reference",
|
||||
"serviceable": false,
|
||||
"sha512": ""
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
|
@ -705,7 +705,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
//start Lua Console if requested in the command line arguments
|
||||
if (_argParser.luaConsole)
|
||||
{
|
||||
Tools.Load<LuaConsole>();
|
||||
OpenLuaConsole();
|
||||
}
|
||||
//load Lua Script if requested in the command line arguments
|
||||
if (_argParser.luaScript != null)
|
||||
|
@ -1475,6 +1475,18 @@ namespace BizHawk.Client.EmuHawk
|
|||
|
||||
private void OpenLuaConsole()
|
||||
{
|
||||
if (!LuaLibraries.IsAvailable)
|
||||
{
|
||||
ShowMessageBox(
|
||||
owner: null,
|
||||
text: "Native Lua dynamic library was unable to be loaded. " + (OSTailoredCode.IsUnixHost
|
||||
? "Make sure Lua is installed with your package manager."
|
||||
: "This library is provided in the dll/ folder, try redownloading BizHawk to fix this error."),
|
||||
caption: "Lua Load Error",
|
||||
EMsgBoxIcon.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
Tools.Load<LuaConsole>();
|
||||
}
|
||||
|
||||
|
|
|
@ -9,14 +9,16 @@ using System.Threading;
|
|||
using NLua;
|
||||
using NLua.Native;
|
||||
|
||||
using BizHawk.Client.Common;
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Client.Common;
|
||||
|
||||
namespace BizHawk.Client.EmuHawk
|
||||
{
|
||||
public class LuaLibraries : ILuaLibraries
|
||||
{
|
||||
public static readonly bool IsAvailable = LuaNativeMethodLoader.EnsureNativeMethodsLoaded();
|
||||
|
||||
public LuaLibraries(
|
||||
LuaFileList scriptList,
|
||||
LuaFunctionList registeredFuncList,
|
||||
|
@ -28,6 +30,11 @@ namespace BizHawk.Client.EmuHawk
|
|||
IEmulator emulator,
|
||||
IGameInfo game)
|
||||
{
|
||||
if (!IsAvailable)
|
||||
{
|
||||
throw new InvalidOperationException("The Lua dynamic library was not able to be loaded");
|
||||
}
|
||||
|
||||
void EnumerateLuaFunctions(string name, Type type, LuaLibraryBase instance)
|
||||
{
|
||||
if (instance != null) _lua.NewTable(name);
|
||||
|
@ -302,8 +309,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
LuaFile luaFile,
|
||||
string name = null)
|
||||
{
|
||||
var nlf = new NamedLuaFunction(function, theEvent, logCallback, luaFile,
|
||||
() => { _lua.NewThread(out var thread); return thread; }, name);
|
||||
var nlf = new NamedLuaFunction(function, theEvent, logCallback, luaFile, () => _lua.NewThread(), name);
|
||||
RegisteredFunctions.Add(nlf);
|
||||
return nlf;
|
||||
}
|
||||
|
@ -320,8 +326,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
{
|
||||
var content = File.ReadAllText(file);
|
||||
var main = _lua.LoadString(content, "main");
|
||||
_lua.NewThread(main, out var ret);
|
||||
return ret;
|
||||
return _lua.NewThread(main);
|
||||
}
|
||||
|
||||
public void SpawnAndSetFileThread(string pathToLoad, LuaFile lf)
|
||||
|
|
|
@ -1,16 +1,9 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using BizHawk.Common.PathExtensions;
|
||||
|
||||
namespace BizHawk.Common
|
||||
{
|
||||
/// <summary>Implementors are able to provide pointers to functions in dynamically-linked libraries, which are loaded through some undefined mechanism.</summary>
|
||||
/// <seealso cref="PatchImportResolver"/>
|
||||
public interface IImportResolver
|
||||
{
|
||||
IntPtr GetProcAddrOrZero(string entryPoint);
|
||||
|
@ -21,50 +14,6 @@ namespace BizHawk.Common
|
|||
|
||||
public class DynamicLibraryImportResolver : IDisposable, IImportResolver
|
||||
{
|
||||
private static readonly IReadOnlyCollection<string> UnixSearchPaths;
|
||||
|
||||
static DynamicLibraryImportResolver()
|
||||
{
|
||||
var currDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase)?.Replace("file:", "") ?? string.Empty;
|
||||
var sysLibDir = Environment.GetEnvironmentVariable("BIZHAWK_INT_SYSLIB_PATH") ?? "/usr/lib";
|
||||
UnixSearchPaths = new[]
|
||||
{
|
||||
$"{currDir}/", $"{currDir}/dll/",
|
||||
$"{sysLibDir}/bizhawk/", $"{sysLibDir}/", $"{sysLibDir}/mupen64plus/"
|
||||
};
|
||||
}
|
||||
|
||||
private static string UnixResolveFilePath(string orig) => orig.IsAbsolute()
|
||||
? orig
|
||||
: UnixSearchPaths.Select(dir => dir + orig)
|
||||
.FirstOrDefault(s =>
|
||||
{
|
||||
var fi = new FileInfo(s);
|
||||
return fi.Exists && (fi.Attributes & FileAttributes.Directory) != FileAttributes.Directory;
|
||||
})
|
||||
?? orig; // don't MakeAbsolute, just pass through and hope something lower-level magically makes it work
|
||||
|
||||
// hack for Lua since it needs to be opened as global for modules to find lua symbols
|
||||
[DllImport("libdl.so.2")]
|
||||
private static extern IntPtr dlopen(string fileName, int flags);
|
||||
public void UnixMakeGlobal(string path)
|
||||
{
|
||||
if (!OSTailoredCode.IsUnixHost)
|
||||
{
|
||||
throw new NotSupportedException("This method is not suitable for non-Unix hosts");
|
||||
}
|
||||
|
||||
OSTailoredCode.LinkedLibManager.FreeByPtr(_p);
|
||||
path = UnixResolveFilePath(path);
|
||||
_p = dlopen(path, 0x102 /* RTLD_NOW | RTLD_GLOBAL */);
|
||||
if (_p == IntPtr.Zero)
|
||||
{
|
||||
// I guess RTLD_GLOBAL isn't supported?
|
||||
Console.WriteLine($"Attempt to globalize {path} failed! Reverting back to local load...");
|
||||
_p = OSTailoredCode.LinkedLibManager.LoadOrThrow(path);
|
||||
}
|
||||
}
|
||||
|
||||
private IntPtr _p;
|
||||
|
||||
public readonly bool HasLimitedLifetime;
|
||||
|
@ -72,7 +21,9 @@ namespace BizHawk.Common
|
|||
/// <param name="hasLimitedLifetime">will never be unloaded iff false (like <see cref="DllImportAttribute">[DllImport]</see>)</param>
|
||||
public DynamicLibraryImportResolver(string dllName, bool hasLimitedLifetime = true)
|
||||
{
|
||||
_p = OSTailoredCode.LinkedLibManager.LoadOrThrow(OSTailoredCode.IsUnixHost ? UnixResolveFilePath(dllName) : dllName); // on Windows, EmuHawk modifies its process' search path
|
||||
// on Windows, SetDllDirectoryW is used to adjust .dll searches
|
||||
// on Linux, LD_LIBRARY_PATH is set to adjust .so searches
|
||||
_p = OSTailoredCode.LinkedLibManager.LoadOrThrow(dllName);
|
||||
HasLimitedLifetime = hasLimitedLifetime;
|
||||
if (!hasLimitedLifetime) GC.SuppressFinalize(this);
|
||||
}
|
||||
|
@ -99,72 +50,4 @@ namespace BizHawk.Common
|
|||
DisposeHelper();
|
||||
}
|
||||
}
|
||||
|
||||
public class InstanceDll : IDisposable, IImportResolver
|
||||
{
|
||||
public IntPtr HModule { get; private set; }
|
||||
|
||||
public InstanceDll(string dllPath)
|
||||
{
|
||||
// copy the dll to a temp directory
|
||||
var path = TempFileManager.GetTempFilename(Path.GetFileNameWithoutExtension(dllPath), ".dll", false);
|
||||
File.Copy(dllPath, path, true);
|
||||
// try to locate dlls in the current directory (for libretro cores)
|
||||
// this isn't foolproof but it's a little better than nothing
|
||||
// setting PWD temporarily doesn't work. that'd be ideal since it supposedly gets searched early on,
|
||||
// but i guess not with SetDllDirectory in effect
|
||||
var envpath = Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.Process);
|
||||
try
|
||||
{
|
||||
var envpath_new = $"{Path.GetDirectoryName(path)};{envpath}";
|
||||
Environment.SetEnvironmentVariable("PATH", envpath_new, EnvironmentVariableTarget.Process);
|
||||
HModule = OSTailoredCode.LinkedLibManager.LoadOrThrow(path); // consider using LoadLibraryEx instead of shenanigans?
|
||||
var newfname = TempFileManager.RenameTempFilenameForDelete(path);
|
||||
File.Move(path, newfname);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
Environment.SetEnvironmentVariable("PATH", envpath, EnvironmentVariableTarget.Process);
|
||||
}
|
||||
|
||||
public IntPtr GetProcAddrOrZero(string procName) => OSTailoredCode.LinkedLibManager.GetProcAddrOrZero(HModule, procName);
|
||||
|
||||
public IntPtr GetProcAddrOrThrow(string procName) => OSTailoredCode.LinkedLibManager.GetProcAddrOrThrow(HModule, procName);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (HModule == IntPtr.Zero) return; // already freed
|
||||
OSTailoredCode.LinkedLibManager.FreeByPtr(HModule);
|
||||
HModule = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Aggregates <see cref="IImportResolver">resolvers</see>, resolving addresses by searching through them, starting with the last.</summary>
|
||||
public class PatchImportResolver : IImportResolver
|
||||
{
|
||||
private readonly List<IImportResolver> _resolvers;
|
||||
|
||||
public PatchImportResolver(params IImportResolver[] resolvers)
|
||||
{
|
||||
_resolvers = resolvers.ToList();
|
||||
}
|
||||
|
||||
public IntPtr GetProcAddrOrZero(string entryPoint)
|
||||
{
|
||||
for (var i = _resolvers.Count - 1; i != 0; i--)
|
||||
{
|
||||
var ret = _resolvers[i].GetProcAddrOrZero(entryPoint);
|
||||
if (ret != IntPtr.Zero) return ret;
|
||||
}
|
||||
return _resolvers[0].GetProcAddrOrZero(entryPoint); // if it's Zero/NULL, return it anyway - the search failed
|
||||
}
|
||||
|
||||
public IntPtr GetProcAddrOrThrow(string entryPoint)
|
||||
{
|
||||
var ret = GetProcAddrOrZero(entryPoint);
|
||||
return ret != IntPtr.Zero ? ret : throw new InvalidOperationException($"{entryPoint} was not found in any of the aggregated resolvers");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue