在Luabind中的自定义构造函数

我正在使用Luabind将C++ API绑定到Lua。我有一些无法直接创建的对象,而是必须在另一个线程上创建。我目前通过定义一个名为create的“静态”成员来处理这个问题,该成员会一直yield,直到对象被创建:

luabind::class_<Foo>("Foo")
  .scope
  [
    luabind::def("create", &someCreateMethod, luabind::yield)
  ]

这个方法可行,但缺点是使客户端API变得复杂。对于这些类,您无法以正常方式创建它们(例如,local f = Foo()),而是需要执行local f = Foo.create()

是否可能定义一个Luabind构造函数,它不实际调用C++构造函数,而是调用另一个返回构造对象的函数(并在此期间可以yield)?我已尝试定义__init__call的绑定(后者在scope下定义了它,以定义它在类而不是实例上),但我没有成功。

原文链接 https://stackoverflow.com/questions/8115263

点赞
stackoverflow用户734069
stackoverflow用户734069

Luabind 中的构造函数必须是实际的 C++ 类构造函数。所以你得处理一下略微奇怪的 API。

如果你只关心如何将 Foo 用作构造函数方法,那么可以这样做。将你的 C++ 类 Foo 登记为 FooLua,并将 someCreateMethod 注册为 Lua 的自由函数 Foo,而不是 FooLua 的成员。因此,对于用户而言,Foo 是 Lua 类 Foo 的构造函数。

但这会限制你赋予 Foo 其他静态属性(如成员等)的能力。但你可以通过一些直接的 Lua API 编码来实现。你可以创建一个空表 Foo,为其创建一个 metatable,并将其中的 __index__newindex 调用转发到 FooLua。同样地,你可以覆盖这个 metatable 的 __call,将构造转发到 Foo.create

2011-11-13 23:57:44
stackoverflow用户1879228
stackoverflow用户1879228

虽然 luabind 没有提供直接定义自定义构造函数的途径,但是通过一些技巧是可能的:

template<typename T,auto TCnstrct,typename ...TArgs>
static void custom_constructor(luabind::argument const &self_, TArgs... args)
{
    using holder_type = luabind::detail::value_holder<T>;
    luabind::detail::object_rep* self = luabind::touserdata<luabind::detail::object_rep>(self_);

    void* storage = self->allocate(sizeof(holder_type));
    self->set_instance(new (storage) holder_type(nullptr,TCnstrct(std::forward<TArgs>(args)...)));
}

template<typename T,auto TCnstrct,typename ...TArgs>
    static void define_custom_constructor(lua_State *l)
{
    auto *registry = luabind::detail::class_registry::get_registry(l);
    auto *crep = registry->find_class(typeid(T));
    assert(crep);
    auto fn = luabind::make_function(l,&custom_constructor<T,TCnstrct,TArgs...>);
    crep->get_table(l);
    auto o = luabind::object{luabind::from_stack(l,-1)};
    luabind::detail::add_overload(o,"__init",fn);
    lua_pop(l,1);
}

这将允许您在类定义之后使用任何自由函数作为构造函数:

static void define_vector_class(lua_State *l)
{
    auto modMath = luabind::module_(l,"math");
    struct Vector
    {
        Vector()=default;
        float x,y,z;
    };
    auto defVec = luabind::class_<Vector>("Vector");
    modMath[defVec];

    // 定义接受三个浮点型参数的自定义构造函数
    define_custom_constructor<Vector,[](float x,float y,float z) -> Vector {
        Vector v;
        v.x = x;
        v.y = y;
        v.z = z;
        return v;
    },float,float,float>(l); // 构造函数参数类型也必须在模板参数列表中指定
}

在 luabind 的 deboostified 版本中进行了测试(https://github.com/decimad/luabind-deboostified),但是它也应该适用于常规版本。

2021-08-28 15:58:17