对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调用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互相调用的一个简单理解。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • lua作为小巧精悍的脚本语言,易于嵌入c/c++中 , 广泛应用于游戏AI ,实际上在任何经常变化的逻辑上都可以使...
    木易林1阅读 1,531评论 0 4
  • 1. 写在前面 很多时候我们都需要借助一些脚本语言来为我们实现一些动态的配置,那么就会涉及到如何让脚本语言跟原生语...
    杰嗒嗒的阿杰阅读 3,456评论 9 31
  • 第一篇 语言 第0章 序言 Lua仅让你用少量的代码解决关键问题。 Lua所提供的机制是C不擅长的:高级语言,动态...
    testfor阅读 2,725评论 1 7
  • 第六章 证据是什么? 为什么如此多的写作和演说由一个又一个观点堆砌而成,而很少或根本就没有提供支持这些观点的证据?...
    露露黎阅读 367评论 0 0
  • 治保主任尴尬地示意小赵,"我媳妇。" 治保主任媳妇就不客气了,毕竟小赵抱的是她老公。 "你年纪轻轻的,找这么个老汉...
    tianguozheng阅读 325评论 0 0