Lua ,C,C#互相調用的理解
-
幾種情況討論
- C調用Lua
- C調用C#
- C#調用C
- C#調用Lua
- Lua調用C
- Lua調用C#
Lua調用C
本質上是定義一個lua_CFunction,然後通過把關聯到Lua中的一個table中,默認的比如lua_register,實際上是把這個函數關聯到global表的對應key上,其他的也可以關聯到自己定義的table上,比如:
- lua_rawget 獲取註冊表中的table
- lua_pushstring 導出的函數名
- lua_pushcfunction,導出的函數
- lua_rawset 設置關聯
lua_pushstring(l,"export_table");lua_rawget(l,LUA_REGISTRYINDEX);if (lua_istable(l,-1)){ lua_pushstring(l,"function_name"); lua_pushcfunction(l,lua_CFunction_define); // 相當於export_table[function_name] = lua_CFunction_define; lua_rawset(l,-3);}lua_pop(l, 1);
C調用Lua
通過lua_call和lua_pcall實現,先把函數壓棧,這裡的函數是在lua中的function,由於上面C函數可以關聯到lua的某個table中,所以,理論上也可以是C函數,然後把返回結果再壓棧。具體參數含義見API說明。
The following example shows how the host program can do the equivalent to this Lua code:
a = f("how", t.x, 14)
Here it is in C:
lua_getfield(L, LUA_GLOBALSINDEX, "f"); /* function to be called */ lua_pushstring(L, "how"); /* 1st argument */ lua_getfield(L, LUA_GLOBALSINDEX, "t"); /* table to be indexed */ lua_getfield(L, -1, "x"); /* push result of t.x (2nd arg) */ lua_remove(L, -2); /* remove "t" from the stack */ lua_pushinteger(L, 14); /* 3rd argument */ lua_call(L, 3, 1); /* call "f" with 3 arguments and 1 result */ lua_setfield(L, LUA_GLOBALSINDEX, "a"); /* set global "a" */
Note that the code above is 「balanced」: at its end, the stack is back to its original configuration. This is considered good programming practice.
以上引用自官方Manual
C#調用C
C#調用C的代碼是通過P/invoke, 即平台調用,.net 提供了一種託管代碼調用非託管代碼的機制。
通過DllImport特性實現,把c的相關函數聲明成 static, extern的形式,還可以為方法的參數和返回值指定自定義封送處理信息。
具體可以參考MSDN的描述
C調用C#
C代碼調用C#是通過delegate實現的,即把需要被調用的C#函數都聲明成delegate,然後通過把函數地址通過DllImport已經導出的函數傳入非託管代碼(C代碼),其中Marshal.GetFunctionPointerForDelegate可以獲取函數指針。
有了上面的過程,下面的就好說了
C#調用Lua
C# —》C —》Lua
- 把Lua相關的API,DLlIMPORT到C#
- 把需要調用的Lua函數用上面導出的函數壓棧
- 調用導出的C#函數,pcall
Lua調用C#
Lua —》C —》C#, 以下部分代碼摘自Slua
- 把需要被調用的C#函數聲明為delegate,由於Lua與C的通訊是通過lua_CFunction,所以這裡我們聲明的形式也要是一樣的
public delegate int LuaCSFunction(IntPtr luaState);
- 把Lua調用C相關的Lua API通過DllImport到C#,比如lua_pushcfunction
[DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]public static extern void lua_pushcclosure(IntPtr l, IntPtr f, int nup);public static void lua_pushcclosure(IntPtr l, LuaCSFunction f, int nup){ IntPtr fn = Marshal.GetFunctionPointerForDelegate(f); lua_pushcclosure(l, fn, nup);}
- 通過C#調用Lua的相關API,註冊C#函數到Lua,與上面Lua調用C的註冊過程是一樣的
LuaDLL.lua_pushcfunction(L, print);LuaDLL.lua_setglobal(L, "print");
print定義如下
static int print(IntPtr L)
以上就是C,C#,Lua互相調用的一個簡單理解。
推薦閱讀:
※再議Unity優化
※是誰在使用 C#/VB.NET/Delphi?
※如何評價 qwas982 請求 C# 團隊開發特製的中文版的行為?
※.NET 的性能很差嗎?