function - Luabind 是如何工作的?

标签 function lua wrapper bind

我对 Luabind 包装器如何在没有 lua_State *L 的情况下传递函数感兴趣。并且不使用 Lua 堆栈。

Luabind 如何:

  • 计算函数参数?
  • 将函数参数链接到 Lua 堆栈?
  • 链接这些类(class)

  • 我不是想创建另一个像 Luabind 这样的绑定(bind)到其他库。我只是想知道他们是怎么做到的。只是一个好奇的人。

    最佳答案

    好问题。我对 luabind 的工作方式有一些模糊的概念,但我没有足够的知识来完整准确地回答。借助 IDE 和调试器,我开始剖析以下非常简单的部分:

    struct C
    {
        int i;
        int f(int x, const char* s)
    };
    
        lua_State* L = luaL_newstate();
    
    open(L);
    module(L)
    [
        class_<C>("C")
            .def_readwrite("index", &C::i)
            .def("f", &C::f)
    ];
    

    首先要注意的是 L大量传递给 luabind,调用 open在 Lua 状态中创建一些全局变量:__luabind_classes userdata 类型和两个函数 classproperty . Luabind 似乎没有使用全局变量——它需要的一切都保存在 lua 环境中。

    现在我们到达 module(L)[...] .原始代码是最好的解释,这里首先是module :
    inline module_ module(lua_State* L, char const* name = 0)
    {
        return module_(L, name);
    }
    

    很简单,这里是 module_ :
    class LUABIND_API module_
    {
    public:
        module_(lua_State* L_, char const* name);
        void operator[](scope s);
    
    private:
        lua_State* m_state;
        char const* m_name;
    };
    

    所以我们的小程序所做的是在 module_ 上调用 operator []。具有一些定义的类(即 scope 参数),但 module_类知道在哪个 Lua 状态下运行。 scope类也很有趣(有些部分被省略了,有些部分稍微简化了):
    struct LUABIND_API scope
    {
        //...
        explicit scope(detail::registration* reg);
        scope& operator,(scope s);
        void register_(lua_State* L) const;
    private:
        detail::registration* m_chain;
    };
    
    scope正在构建 detail::registration 的链表节点,该列表来自使用 operator, .所以当一个人做module(L) [class_<...>..., class_<...>...] , class_继承自 scopedetail::registration 初始化它的基数实例,然后是 scope 的逗号运算符建立一个所有注册的链表,传递给 module_::operator[]调用 scope::register_依次枚举链并调用 register_所有这些detail::registration对象。 lua_State总是传递给 register_ .

    呸。现在让我们看看当一个人这样做时会发生什么class_<C>("C").def("f", &C::f) .这构造了 class_<C> 的实例detail::registration 中的某个名称成员(member) class_ .调用class_::def方法写入 reg 结构等等,但这里有一个非常有趣的行,位于 def 的调用链中。 :
                object fn = make_function(
                    L, f, deduce_signature(f, (Class*)0), policies);
    

    哦,deduce_signature ,我真的很想看看。现在我想取消它,但它的工作方式是这样的:通过由 boost ( BOOST_PP_ITERATE 和其他一些实用程序) 辅助的暗预处理器巫术,为 1 和 LUABIND_MAX_ARITY 之间的每个 N 生成以下内容:
    template <class R, class T, class A1, classA2, ..., classAN>
    boost::mpl::vectorN_PLUS_2<R, T, A1, A2, ..., AN>  // type of return value
         deduce_signature(R(T::*)(A1, A2, ..., AN))
         {
              return boost::mpl::vectorN_PLUS_2<R, T, A1, A2, ..., AN>()
         }
    

    同样,为 1 和 LUABIND_MAX_ARITY 之间的所有 N 生成这样的函数,默认情况下为 10。有几个重载来处理 const 方法、虚拟包装器和自由函数等,这意味着大约有 50 deduce_signature在预处理器之后和编译开始之前最终出现在您的源代码中的函数。从那里,编译器的工作就是选择正确的 deduce_signature传递给 def 的函数重载这将返回正确的 boost::mpl::vectorX 类型。从那里 make_function可以做任何事情——它有一个参数类型的 [compile time] 列表,并通过更多的模板魔术来计算这些参数类型,并与 Lua 值相互转换等等。

    这就是我要停下来的地方。调查基于 Luabind 0.8.1。随意浏览/调试 Luabind 的代码以获得更多答案 - 这需要一些时间,但在你习惯了这种风格后并不难 :) 祝你好运。

    TL;DR: 魔法……黑魔法

    关于function - Luabind 是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6114765/

    相关文章:

    Java 包装器到 Perl/Python 代码

    Swift自动函数反转

    javascript - 排名扑克手

    c - 在 C 中将未初始化的二维数组作为参数传递

    lua - Lua:什么时候可以使用冒号语法?

    php - 如何获取URI的特定部分?

    javascript - init后直接调用函数

    multidimensional-array - Lua - 编写类似于 ipairs 的迭代器,但选择索引

    Nginx lua日志位置

    css - 文本不在包装内垂直拉伸(stretch)的 Div