-
几种情况讨论
- 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调用CS
C代码调用C#是通过delegate实现的,即把需要被调用的C#函数都声明成delegate,然后通过把函数地址通过DllImport已经导出的函数传入非托管代码(C代码),其中Marshal.GetFunctionPointerForDelegate可以获取函数指针。
有了上面的过程,下面的就好说了
C#调用Lua
C# --》C --》Lua
- 把Lua相关的API,DLlIMPORT到C#
- 把需要调用的Lua函数用上面导出的函数压栈
- 调用导出的C#函数,pcall
Lua调用CS
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互相调用的一个简单理解。