Я думаю, что для того, чтобы работать, вы должны связать свой производный класс, как это:
luabind::class_<Button, BaseWidget, std::shared_ptr<Button>> ("Button")
Например:
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;
}
};
Теперь вы можете использовать его с 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)
];
}
};
В луа:
b = Button()
a = Action()
a:DoClick(b)
Причина в том, что luabind использует систему идентификаторов типов с целыми числами (точнее std :: size_t, как определено в inheritance.hpp).
Вы можете получить тип-идентификатор любого зарегистрированного типа с функцией:
luabind::detail::static_class_id<T>(nullptr);
где T является зарегистрированным классом.
В моей демонстрационной программе они:
- BaseWidget = 3
- станд :: shared_ptr < BaseWidget> = 6
- Кнопка = 4
- станд :: shared_ptr < Button> = 7
- Действие = 5
Поэтому, когда вы вызываете DoClick из lua, он будет называть элемент get t он шаблонный класс pointer_holder в 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
);
}
Как вы можете видеть, если целевой класс не то же самое, как один зарегистрированный, он будет пытаться сделать бросок.
Здесь все становится интересным. Если вы объявили класс Button, как
luabind::class_<Button, BaseWidget,std::shared_ptr<BaseWidget>>("Button")
то экземпляр будет проходить как shared_ptr к BaseWidget, таким образом, функция преобразования будет пытаться отлиты из BaseWidget (3) к StD :: shared_ptr < Button> (7), и это терпит неудачу. Он может работать, если luabind поддерживает преобразование базы в производную, чего, по-видимому, нет.
Если же вы объявили класс Button как
luabind::class_<Button, BaseWidget, std::shared_ptr<Button>> ("Button")
то экземпляр будет проходить в качестве shared_ptr к кнопке, а затем целевой идентификатор будет соответствовать зарегистрированному типу. Функция get будет входить в первую очередь, никогда не беспокоясь о приведении.
Вы также можете найти автономную программу, которую я использовал here at pastebin.
А вот список интересных точек останова вы можете установить, чтобы увидеть, что происходит (Luabind версия 900):
- линии 94 в instance_holder.hpp (первая линия pointer_holder :: получить)
- строка 143 в instance.cpp (первой линии cast_graph :: осущ :: гипсе)
не следует ли, что вторая линия использование 'станд :: shared_ptr' 'не станд :: shared_ptr
Да - спасибо! Просто тип tho! – ltjax