虽然 luabind 没有提供一种直接的方式来定义自定义构造函数,但实际上它可以通过一些 hack 来实现:
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 taking three float arguments
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); // Constructor parameter types have to be specified in template parameter list as well
}
使用 luabind 的 deboostified 版本 ( https://github.com/decimad/luabind-deboostified ) 进行了测试,但它也应该适用于常规版本。