对Lua ,C,C#互相调用的理解

作者: bYsdTd | 来源:发表于2017-03-24 23:03 被阅读1275次
    • 几种情况讨论

    • 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#互相调用的理解

        本文链接:https://www.haomeiwen.com/subject/qqeqottx.html