c# - 如何从 Lua 调用 C# 委托,委托可以抛出异常
问题描述
在基于 Linux 的 docker 映像中运行以下代码会导致 CLR 崩溃。
static void Main(string[] args)
{
System.Console.WriteLine("Starting program");
using (NLua.Lua luaState = new NLua.Lua())
{
System.Action invoke = () => throw new System.Exception("message");
luaState["invoke"] = invoke;
try
{
System.Console.WriteLine("Invoking delegate");
luaState.DoString(@"invoke()");
}
catch (System.Exception ex)
{
// We never get here
System.Console.WriteLine("Exception caught");
throw;
}
}
}
难道我做错了什么?
Dockerfile 是 Visual Studio 的默认建议,进程是从 Visual Studio 启动的。
在 Docker 之外运行程序,即。在 Windows 主机上,按预期工作。(命中 catch 块并且不会导致 CLR 上的致命情况)
将调用包装在 apcall
中并不能解决问题。
可以通过注册函数而不是发送委托来避免这个问题。如果委托没有抛出异常,它将按预期调用。
图片中的控制台日志;
Starting program
Invoking delegate
Unhandled exception. System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
---> System.Exception: message
at LuaTest.Program.<>c.<Main>b__0_0() in C:\Source\Tests\LuaTest\Program.cs:line 10
--- End of inner exception stack trace ---
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
at NLua.MetaFunctions.CallDelegateInternal(Lua luaState)
at NLua.MetaFunctions.CallDelegate(IntPtr state)
at KeraLua.NativeMethods.lua_pcallk(IntPtr luaState, Int32 nargs, Int32 nresults, Int32 errorfunc, IntPtr ctx, IntPtr k)
at KeraLua.Lua.PCall(Int32 arguments, Int32 results, Int32 errorFunctionIndex)
at NLua.Lua.DoString(String chunk, String chunkName)
at LuaTest.Program.Main(String[] args) in C:\Source\Tests\LuaTest\Program.cs:line 15
Fatal error. Internal CLR error. (0x80131506)
at KeraLua.NativeMethods.lua_pcallk(IntPtr, Int32, Int32, Int32, IntPtr, IntPtr)
at KeraLua.NativeMethods.lua_pcallk(IntPtr, Int32, Int32, Int32, IntPtr, IntPtr)
at KeraLua.Lua.PCall(Int32, Int32, Int32)
at NLua.Lua.DoString(System.String, System.String)
at LuaTest.Program.Main(System.String[])
解决方案
自我回答;
这似乎是 NLua 中的一个错误MetaFunctions.CallDelegate
。委托的调用不在 try-catch 块中。对比LuaMethodWrapper.Call
。
致命的可能是由于尝试通过调用 longjmp 的非托管代码传播异常引起的。请参阅有关异常互操作性的 dotnet 核心说明
最直接的解决方法是使用注册函数注册委托。
Action action=()=>throw new Exception()
luastate.RegisterFunction("invoke",action.Target,action.Method);
推荐阅读
- reactjs - 找不到模块:错误:无法解析“react-module-test”
- maven - 如何将 Maven Profiles 值传递给 Spring Bean XML
- android - 在 Android 的 Application 类中为 DI 创建所有模块
- html - 在 Angular 中使用对象的动态选择选项
- c - 删除动态指针数组中单元格的正确方法
- javascript - Vue-Bootstrap 不适用于 Django。我怎样才能正确开始呢?
- z3 - Z3 求解器输出 CUT 2
- java - Android XML 解析错误(无效的令牌,格式不正确)
- ionic-framework - 离子应用程序无法使用数据库动态更新
- javascript - toLocaleString api 不适用于 hi-IN 语言环境