从Lua调用c#时的AccessViolationException

本文关键字:时的 AccessViolationException 调用 Lua | 更新日期: 2023-09-27 18:10:33

我正在尝试使用Lua (C)与c#,我已经导入了一些函数来测试这一点,一切似乎都工作,直到我尝试从Lua调用c#函数。

static void Main(string[] args)
{
    var L = Lua.luaL_newstate();
    Lua.luaL_openlibs(L);
    Lua.lua_register(L, "test", Test);
    Lua.luaL_dostring(L, "test()");
}
static int Test(IntPtr L)
{
    Console.WriteLine("Test from lua->C#");
    return 0;
}

如果我运行这段代码,我得到了测试消息,但在此之后,它抛出了一个AccessViolationException:

// #define luaL_dostring(L, s) (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0))
public static int luaL_dostring(IntPtr L, string s)
{
    if (luaL_loadstring(L, s) != 0)
        return 1;
    if (lua_pcall(L, 0, LUA_MULTRET, 0) != 0) // <<<<<<<<<<<<<<<<<<<<<<<<
        return 1;
    return 0;
}

这是我的整个导入代码:

public static class Lua
{
    public const int LUA_MULTRET = -1;
    //[return: MarshalAs(UnmanagedType.SysInt)]
    public delegate int LuaNativeFunction(IntPtr L);
    [DllImport("lua51.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
    public static extern IntPtr luaL_newstate();
    [DllImport("lua51.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
    public static extern void luaL_openlibs(IntPtr L);
    [DllImport("lua51.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
    public static extern int luaL_loadbuffer(IntPtr L, [MarshalAs(UnmanagedType.LPStr)] string buff, int size, [MarshalAs(UnmanagedType.LPStr)] string name);
    // LUA_API int lua_resume (lua_State *L, int nargs)
    [DllImport("lua51.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
    public static extern int lua_resume(IntPtr L, int nargs);
    // static int lua_pcall(lua_State*L,int nargs,int nresults,int errfunc)
    [DllImport("lua51.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
    public static extern int lua_pcall(IntPtr L, int nargs, int nresults, int errfunc);
    // static void lua_pushcclosure(lua_State*L,lua_CFunction fn,int n)
    [DllImport("lua51.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
    public static extern int lua_pushcclosure(IntPtr L, LuaNativeFunction fn, int n);
    // static void lua_setfield(lua_State*L,int idx,const char*k);
    [DllImport("lua51.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
    public static extern int lua_setfield(IntPtr L, int idx, [MarshalAs(UnmanagedType.LPStr)] string k);
    // LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s)
    public static int luaL_loadstring(IntPtr L, string s)
    {
        return luaL_loadbuffer(L, s, s.Length, s);
    }
    // #define luaL_dostring(L, s) (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0))
    public static int luaL_dostring(IntPtr L, string s)
    {
        if (luaL_loadstring(L, s) != 0)
            return 1;
        if (lua_pcall(L, 0, LUA_MULTRET, 0) != 0)
            return 1;
        return 0;
    }
    // #define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n)))
    public static void lua_register(IntPtr L, string n, LuaNativeFunction f)
    {
        lua_pushcfunction(L, f);
        lua_setglobal(L, n);
    }
    // #define lua_pushcfunction(L,f)   lua_pushcclosure(L, (f), 0)
    public static void lua_pushcfunction(IntPtr L, LuaNativeFunction f)
    {
        lua_pushcclosure(L, f, 0);
    }
    // #define lua_setglobal(L,s)lua_setfield(L,(-10002),(s))
    public static void lua_setglobal(IntPtr L, string s)
    {
        lua_setfield(L, -10002, s);
    }
}

因为我读到这可能是由委托返回值的类型不匹配引起的:我运行的是Windows 7 x64, Lua dll是x86,项目也设置为使用x86。我还尝试为LuaNativeFunction设置一个返回封送,因为这是在其他地方建议的,但这并没有改变任何东西。

[return: MarshalAs(UnmanagedType.I4)]
public delegate int LuaNativeFunction(IntPtr L);

有人知道是什么问题吗?

更新:使用x64 Lua库与x64目标解决了它,所以我想这是问题的某种程度上,但我不太理解为什么

从Lua调用c#时的AccessViolationException

Lua DLL是使用CDecl调用约定编译的,您需要在所有DllImport属性和所有用作回调的委托上指定此约定。例如,你的LuaNativeFunction委托需要声明为:

[UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.Cdecl‌​)]
[return: MarshalAs(UnmanagedType.I4)]
public delegate int LuaNativeFunction(IntPtr L);

认为,