2015-08-30 47 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); 

問候,

相關問題