代码之家  ›  专栏  ›  技术社区  ›  Mars

从Lua调用C#时发生AccessViolationException

  •  0
  • Mars  · 技术社区  · 10 年前

    我正在尝试将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目标解决了这个问题,所以我想这就是问题所在,但我不太明白 为什么? .

    1 回复  |  直到 10 年前
        1
  •  1
  •   Yanos    10 年前

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

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

    当做