2015-08-30 2 views
0

Я пытаюсь использовать Lua (C) с C#, я импортировал некоторые функции для проверки этого, и все, кажется, работает, пока я не попытаюсь вызвать функцию C# из Lua.AccessViolationException при вызове C# из Lua

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); 

С уважением,

Смежные вопросы