Creo que para que eso funcione hay que unir su clase derivada de esta manera:
luabind::class_<Button, BaseWidget, std::shared_ptr<Button>> ("Button")
Por ejemplo:
class BaseWidget
{
public:
static void Bind2Lua(lua_State* l)
{
luabind::module(l)
[
luabind::class_<BaseWidget, std::shared_ptr<BaseWidget>> ("BaseWidget")
.def(luabind::constructor<>())
];
}
virtual ~BaseWidget()
{
}
};
class Button : public BaseWidget
{
public:
static void Bind2Lua(lua_State* l)
{
luabind::module(l)
[
luabind::class_<Button, BaseWidget, std::shared_ptr<Button>> ("Button")
.def(luabind::constructor<>())
.def("Click", &Button::Click)
];
}
void Click()
{
std::cout << "Button::Click" << std::endl;
}
};
Ahora usted puede utilizarlo con shared_ptr:
class Action
{
public:
void DoClick(const std::shared_ptr<Button>& b)
{
// perform click action
b->Click();
}
static void Bind2Lua(lua_State* l)
{
luabind::module(l)
[
luabind::class_<Action> ("Action")
.def(luabind::constructor<>())
.def("DoClick", &Action::DoClick)
];
}
};
En lua:
b = Button()
a = Action()
a:DoClick(b)
La razón es que luabind utiliza el sistema de identificación tipo con números enteros (más precisamente std :: size_t como se define en inheritance.hpp).
Puede obtener el Tipo-id de cualquier tipo certificada con la función:
luabind::detail::static_class_id<T>(nullptr);
Donde T es la clase registrada.
En mi programa de demostración son:
- BaseWidget = 3
- std :: shared_ptr < BaseWidget> = 6
- botón = 4
- std :: shared_ptr < Button> = 7
- Acción = 5
Así que cuando llame a DoClick desde lua, llamará al miembro get de t que pointer_holder clase de plantilla en instance_holder.hpp:
std::pair<void*, int> get(class_id target) const
{
if (target == registered_class<P>::id)
return std::pair<void*, int>(&this->p, 0);
void* naked_ptr = const_cast<void*>(static_cast<void const*>(
weak ? weak : get_pointer(p)));
if (!naked_ptr)
return std::pair<void*, int>((void*)0, 0);
return get_class()->casts().cast(
naked_ptr
, static_class_id(false ? get_pointer(p) : 0)
, target
, dynamic_id
, dynamic_ptr
);
}
Como se puede ver, si la clase de destino no es el mismo que el registrado, se trata de hacer un reparto.
Aquí es donde las cosas se ponen interesantes. Si usted declaró la clase Button como
luabind::class_<Button, BaseWidget,std::shared_ptr<BaseWidget>>("Button")
continuación, la instancia se llevará a cabo como un shared_ptr a BaseWidget, por tanto, la función de conversión tratará de echar de BaseWidget (3) std :: shared_ptr < Botón> (7) y eso falla. Podría funcionar si luabind admite la conversión de base a derivada, lo que no parece.
Sin embargo, si usted declaró la clase Button como
luabind::class_<Button, BaseWidget, std::shared_ptr<Button>> ("Button")
continuación, la instancia se llevará a cabo como una shared_ptr a Button y entonces el ID de destino coincidirá con el tipo registrado. La función get se ramificará en la primera vuelta, nunca se molestará con el reparto.
También puede encontrar el programa autocontenido que usé here at pastebin.
Y aquí es una lista de puntos de ruptura interesantes que se pueden configurar para ver lo que está pasando (luabind versión 900):
- línea 94 en instance_holder.hpp (primera línea de pointer_holder :: get)
- la línea 143 en instance.cpp (primera línea de cast_graph :: :: impl fundido)
en caso de no uso esa segunda línea 'std :: shared_ptr' 'no std :: shared_ptr
Sí, ¡gracias! ¡Solo un tipo si! – ltjax