原生实现C#和Lua相互调用-Unity3D可用【中】
3.需要注意的几个地方
1. 返回char*时,不可直接使用string替换,否则调用会导致崩溃,因此需要像下面代码展示的那样进行一下转换才可以使用。
[DllImport("CSharpLua", EntryPoint = "lua_tolstring")] private static extern IntPtr _lua_tolstring(IntPtr L, int idx, ref uint size); public static string lua_tolstring(IntPtr L, int idx, ref uint size) { IntPtr buffer = _lua_tolstring(L, idx, ref size); return Marshal.PtrToStringAnsi(buffer); }
2. C#函数传递给Lua使用时,需要使用delegate委托类型。
public delegate int LuaFunction(IntPtr L); [DllImport("CSharpLua", EntryPoint = "lua_pushcclosure")] public static extern void lua_pushcclosure(IntPtr L, LuaFunction func, int idx); public static void lua_pushcfunction(IntPtr L, LuaFunction func) { lua_pushcclosure(L, func, 0); }
3. 在lua源码中定义的宏代码是无法使用的,会提示找不到,需要在C#中手动实现,例如下面展示的2个宏。
#define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s)) #define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, (s))
[DllImport("CSharpLua", EntryPoint = "lua_getfield")] public static extern void lua_getfield(IntPtr L, int idx, string s); public static void lua_getglobal(IntPtr L, string s) { lua_getfield(L, LUA_GLOBALSINDEX, s); } [DllImport("CSharpLua", EntryPoint = "lua_setfield")] public static extern void lua_setfield(IntPtr L, int idx, string s); public static void lua_setglobal(IntPtr L, string s) { lua_setfield(L, LUA_GLOBALSINDEX, s); }
4. 如需要将C#的类实例对象即userdata传递给lua,需要在C#中转换成IntPtr后传递,Lua返回的则需要通过IntPtr转换回C#的实例对象。
[DllImport("CSharpLua", EntryPoint = "lua_pushlightuserdata")] public static extern void _lua_pushlightuserdata(IntPtr L, IntPtr p); public static void lua_pushlightuserdata<T>(IntPtr L, T p) { IntPtr obj = Marshal.GetIUnknownForObject(p); _lua_pushlightuserdata(L, obj); } [DllImport("CSharpLua", EntryPoint = "lua_touserdata")] public static extern IntPtr _lua_touserdata(IntPtr L, int idx); public static T lua_touserdata<T>(IntPtr L, int idx) { IntPtr p = _lua_touserdata(L, idx); return (T)Marshal.GetObjectForIUnknown(p); }