2015-08-30 43 views
0

我想用C#使用Lua(C),我已经导入了一些函数来测试这个,并且似乎一切正常,直到我尝试从Lua调用C#函数。当从Lua调用C#时出现AccessViolationException

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 lib与x64目标解决它,所以我猜这是不知何故的问题,但我不太明白为什么

+1

为了您的委托尝试添加带有属性cdecl调用约定:[UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.Cdecl) ]。 – Yanos

+0

工作,很好:D如果你将它添加为答案,我会接受它。 – Mars

回答

1

Lua DLL使用CDecl调用约定进行编译,并且您需要在所有DllImport属性上指定此参数,并将所有委托用作回调。因此,例如,您LuaNativeFunction代表必须声明为:

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

问候,

相关问题