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 的性能很差嗎?

TAG:Lua | C# | Unity游戏引擎 |