Myślę za to do pracy trzeba związać swoją klasę pochodną tak:
luabind::class_<Button, BaseWidget, std::shared_ptr<Button>> ("Button")
Na przykład:
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;
}
};
Teraz można go używać z 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)
];
}
};
In lua:
b = Button()
a = Action()
a:DoClick(b)
Powodem jest to, że luabind używa systemu typu id z liczbami całkowitymi (dokładniej std :: size_t jak zdefiniowano w dziedziczeniu.hpp).
można uzyskać typu id każdej zarejestrowanej z funkcją typu:
luabind::detail::static_class_id<T>(nullptr);
Jeżeli T jest zarejestrowanym klasa.
W moim programie demonstracyjnym są:
- BaseWidget = 3
- std :: shared_ptr < BaseWidget> = 6
- Przycisk = 4
- std :: shared_ptr < Przycisk> = 7
- Działanie = 5
Tak więc, gdy wywołasz DoClick z lua, zadzwoni do członka pobierania t on szablon klasy pointer_holder w 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
);
}
Jak widać, jeśli klasa docelowa nie jest taki sam jak ten zarejestrowany, to postaram się zrobić odlew.
Tutaj sprawy stają się interesujące. Jeśli zadeklarowana klasa Przycisk jak
luabind::class_<Button, BaseWidget,std::shared_ptr<BaseWidget>>("Button")
następnie wystąpienie odbędzie się jako shared_ptr do BaseWidget, zatem funkcja obsada będzie próbował rzucić z BaseWidget (3) do std :: shared_ptr < przycisk> (7) i to się nie udaje. Mogłoby to działać, gdyby luabind obsługiwał konwersję z bazy do pochodnej, której nie wydaje się.
Jeśli jednak ogłoszony klasę przycisk jako
luabind::class_<Button, BaseWidget, std::shared_ptr<Button>> ("Button")
następnie wystąpienie odbędzie się jako jako shared_ptr na przycisk, a następnie id docelowym będzie pasował zarejestrowanego typu. Funkcja get będzie rozgałęziała się przy pierwszym powrocie, nigdy nie przejmując się obsadą.
Można również znaleźć samodzielny program, którego użyłem: here at pastebin.
A oto lista interesujących punktów przerwy można ustawić, aby zobaczyć, co się dzieje (luabind wersja 900):
- linia 94 w instance_holder.hpp (pierwsza linia pointer_holder :: dostać)
- linia 143 (w instance.cpp pierwszej linii cast_graph :: iMPL :: cast)
nie powinien, że druga linia 'użycie std :: shared_ptr' 'nie std :: shared_ptr
Tak - dziękuję! Tylko typ! – ltjax