Tôi nghĩ cho rằng để làm việc bạn phải ràng buộc lớp được thừa kế của bạn như thế này:
luabind::class_<Button, BaseWidget, std::shared_ptr<Button>> ("Button")
Ví dụ:
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;
}
};
Bây giờ bạn có thể sử dụng nó với 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)
];
}
};
Trong lua:
b = Button()
a = Action()
a:DoClick(b)
Lý do là luabind sử dụng hệ thống loại id với số nguyên (chính xác hơn std :: size_t như được định nghĩa trong inheritance.hpp).
Bạn có thể lấy loại id của bất kỳ loại đăng ký nào có chức năng:
luabind::detail::static_class_id<T>(nullptr);
Trường hợp T là lớp đã đăng ký.
Trong chương trình demo của tôi đó là:
- BaseWidget = 3
- std :: shared_ptr < BaseWidget> = 6
- Button = 4
- std :: shared_ptr < Button> = 7
- Hành động = 5
Vì vậy, khi bạn gọi DoClick từ lua, nó sẽ gọi là thành viên của t anh lớp mẫu pointer_holder trong 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
);
}
Như bạn có thể thấy, nếu lớp mục tiêu không phải là giống như một đăng ký, nó sẽ cố gắng để làm một diễn viên.
Đây là nơi mọi thứ trở nên thú vị. Nếu bạn tuyên bố lớp Button như
luabind::class_<Button, BaseWidget,std::shared_ptr<BaseWidget>>("Button")
thì dụ sẽ được tổ chức như một shared_ptr để BaseWidget, do đó các chức năng dàn diễn viên sẽ cố gắng đúc từ BaseWidget (3) để std :: shared_ptr < Button> (7) và điều đó không thành công. Nó có thể hoạt động nếu luabind hỗ trợ chuyển đổi dựa trên cơ sở, mà nó dường như không.
Tuy nhiên, nếu bạn đã khai báo lớp Button như
luabind::class_<Button, BaseWidget, std::shared_ptr<Button>> ("Button")
thì dụ sẽ được tổ chức như là một shared_ptr để nút và sau đó là id mục tiêu sẽ phù hợp với loại đã đăng ký. Hàm get sẽ phân nhánh trên lần trả về đầu tiên, không bao giờ bận tâm đến dàn diễn viên.
Bạn cũng có thể tìm thấy chương trình tự chứa mình đã sử dụng here at pastebin.
Và đây là danh sách các điểm break thú vị bạn có thể thiết lập để xem những gì đang xảy ra (luabind phiên bản 900):
- dòng 94 trong instance_holder.hpp (dòng đầu tiên của pointer_holder :: get)
- dòng 143 trong instance.cpp (dòng đầu tiên của cast_graph :: impl :: cast)
nên không phải là dòng sử dụng thứ hai 'std :: shared_ptr 'không' std :: shared_ptr
Yea - cảm ơn bạn! Chỉ cần một loại tho! – ltjax