in library/grt/src/grtpp_helper.cpp [322:660]
void generate_class_header(const std::string &dll_export) {
FILE *f = header_file;
// check if we will need a implementation file (.cpp)
if (gstruct->force_impl() || !methods.empty())
needs_body = true;
for (std::map<std::string, MetaClass::Member>::const_iterator iter = members.begin(); iter != members.end();
++iter) {
if (iter->second.delegate_get || iter->second.delegate_set || iter->second.calculated) {
needs_body = true;
break;
}
}
generate_class_doc(f);
fprintf(f, "class %s %s : public %s {\n", needs_body ? dll_export.c_str() : "", cname.c_str(), pname.c_str());
fprintf(f, " typedef %s super;\n\n", pname.c_str());
fprintf(f, "public:\n");
std::string klass = gstruct->get_attribute("simple-impl-data");
if (gstruct->impl_data() || !klass.empty()) {
if (klass.empty()) {
fprintf(f, " class ImplData;\n");
fprintf(f, " friend class ImplData;\n");
} else
fprintf(f, " typedef %s ImplData;\n", klass.c_str());
}
// generate constructors
bool default_ctor_created = false;
for (std::map<std::string, MetaClass::Method>::const_iterator iter = methods.begin(); iter != methods.end();
++iter) {
if (iter->second.constructor) {
fprintf(f, " %s(%s%s, grt::MetaClass *meta = nullptr);\n", cname.c_str(), iter->second.arg_types.empty() ? "" : ", ",
format_arg_list(iter->second.arg_types).c_str());
if (iter->second.arg_types.empty())
default_ctor_created = true;
}
}
if (!default_ctor_created) {
fprintf(f, " %s(grt::MetaClass *meta = nullptr)\n", cname.c_str());
output_constructor_init_list(f);
fprintf(f, " {\n");
// reinit overridden lists
output_overriden_list_reset_code(f);
fprintf(f, " }\n");
fprintf(f, "\n");
}
if (needs_body || !gstruct->get_attribute("simple-impl-data").empty()) {
if (gstruct->get_attribute("simple-impl-data").empty())
fprintf(f, " virtual ~%s();\n\n", cname.c_str());
else {
fprintf(f, " virtual ~%s() {\n if (_release_data && _data)\n _release_data(_data);\n }\n\n", cname.c_str());
}
}
fprintf(f, " static std::string static_class_name() {\n return \"%s\";\n }\n\n", gstruct->name().c_str());
// generate signal access methods
for (MetaClass::SignalList::const_iterator iter = gstruct->get_signals_partial().begin();
iter != gstruct->get_signals_partial().end(); ++iter) {
fprintf(f, " // args: %s\n", format_signal_names(iter->arg_types).c_str());
fprintf(f, " boost::signals2::signal<void (%s)>* signal_%s() { return &_signal_%s; }\n",
format_signal_args(iter->arg_types).c_str(), iter->name.c_str(), iter->name.c_str());
}
// generate member variable accessors
for (MetaClass::MemberList::const_iterator iter = members.begin(); iter != members.end(); ++iter) {
if (iter->second.private_)
continue;
bool overrides_with_same_type = false;
// if the member is overridden, check if the type has been changed
if (iter->second.overrides && gstruct->parent()) {
const MetaClass::Member *member = gstruct->parent()->get_member_info(iter->second.name);
if (member && member->type == iter->second.type)
overrides_with_same_type = true;
}
// getter
if (iter->second.owned_object)
fprintf(f, " // %s is owned by %s\n", iter->second.name.c_str(), cname.c_str());
generate_getter_doc(f, iter->second);
if (iter->second.delegate_get) {
fprintf(f, " %s %s() const;\n", format_type_cpp(iter->second.type).c_str(), iter->second.name.c_str());
} else {
if (iter->second.overrides) {
if (!overrides_with_same_type) {
fprintf(f, " %s %s() const { return %s::cast_from(_%s); }\n", format_type_cpp(iter->second.type).c_str(),
iter->second.name.c_str(), format_type_cpp(iter->second.type).c_str(), iter->second.name.c_str());
} else {
// if we're overriding and the setter is delegated, we need to declare the getter too
if (iter->second.delegate_set)
fprintf(f, " %s %s() const { return super::%s(); }\n", format_type_cpp(iter->second.type).c_str(),
iter->second.name.c_str(), iter->second.name.c_str());
}
} else
fprintf(f, " %s %s() const { return _%s; }\n", format_type_cpp(iter->second.type).c_str(),
iter->second.name.c_str(), iter->second.name.c_str());
}
fprintf(f, "\n");
// setter
if (iter->second.read_only)
fprintf(f, "\nprivate: // The next attribute is read-only.\n");
else
generate_setter_doc(f, iter->second);
if (iter->second.overrides) {
if (overrides_with_same_type) {
// check if the override is for overriding the setter
if (iter->second.delegate_set) {
fprintf(f, " virtual void %s(const %s &value);\n", iter->second.name.c_str(),
format_type_cpp(iter->second.type).c_str());
}
} else {
// variable is overriding another
// list and dict members cannot be changed
if (iter->second.type.base.type != ListType && iter->second.type.base.type != DictType) {
if (iter->second.delegate_set)
fprintf(f, " virtual void %s(const %s &value);\n", iter->second.name.c_str(),
format_type_cpp(iter->second.type).c_str());
else
fprintf(f, " virtual void %s(const %s &value) { super::%s(value); }\n", iter->second.name.c_str(),
format_type_cpp(iter->second.type).c_str(), iter->second.name.c_str());
}
}
} else {
if (iter->second.delegate_set) {
fprintf(f, " virtual void %s(const %s &value);\n", iter->second.name.c_str(),
format_type_cpp(iter->second.type).c_str());
} else { // read-only vars need setter for unserialization if (!iter->second.read_only)
if (!iter->second.calculated) {
fprintf(f, " virtual void %s%s(const %s &value) {\n",
/*iter->second.read_only?"__":*/ "", iter->second.name.c_str(),
format_type_cpp(iter->second.type).c_str());
fprintf(f, " grt::ValueRef ovalue(_%s);\n", iter->second.name.c_str());
if (iter->second.owned_object) {
// if member is owned by this object, we have to mark/unmark it as global
// in case we're in the global tree as well (done in owned_member_changed)
fprintf(f, "\n");
fprintf(f, " _%s = value;\n", iter->second.name.c_str());
fprintf(f, " owned_member_changed(\"%s\", ovalue, value);\n", iter->second.name.c_str());
} else {
fprintf(f, " _%s = value;\n", iter->second.name.c_str());
fprintf(f, " member_changed(\"%s\", ovalue, value);\n", iter->second.name.c_str());
}
fprintf(f, " }\n");
}
}
}
if (iter->second.read_only)
fprintf(f, "public:\n");
fprintf(f, "\n");
}
// generate methods
for (std::map<std::string, MetaClass::Method>::const_iterator iter = methods.begin(); iter != methods.end();
++iter) {
generate_method_doc(f, iter->second);
if (iter->second.abstract)
fprintf(f, " virtual %s %s(%s) = 0;\n", format_type_cpp(iter->second.ret_type, true).c_str(),
iter->second.name.c_str(), format_arg_list(iter->second.arg_types).c_str());
else
fprintf(f, " virtual %s %s(%s);\n", format_type_cpp(iter->second.ret_type, true).c_str(),
iter->second.name.c_str(), format_arg_list(iter->second.arg_types).c_str());
}
if (needs_body || !gstruct->get_attribute("simple-impl-data").empty()) {
bool needs_init = true;
if (gstruct->impl_data()) {
if (gstruct->get_attribute("simple-impl-data").empty()) {
fprintf(f, "\n ImplData *get_data() const { return _data; }\n\n");
fprintf(f, " void set_data(ImplData *data);\n");
} else {
fprintf(f, "\n ImplData *get_data() const { return _data; }\n\n");
fprintf(f, " void set_data(ImplData *data, void (*release)(ImplData*)) {\n");
fprintf(f, " if (_data == data) return;\n");
fprintf(f, " if (_data && _release_data) _release_data(_data);\n");
fprintf(f, " _data= data;\n");
fprintf(f, " _release_data = release;\n");
fprintf(f, " }\n");
needs_init = false;
}
}
if (needs_init) {
fprintf(f, " // default initialization function. auto-called by ObjectRef constructor\n");
fprintf(f, " virtual void init();\n\n");
}
}
fprintf(f, "protected:\n");
// special methods
if (gstruct->watch_lists()) {
fprintf(f, " virtual void owned_list_item_added(grt::internal::OwnedList *list, const grt::ValueRef &value);\n");
fprintf(f,
" virtual void owned_list_item_removed(grt::internal::OwnedList *list, const grt::ValueRef &value);\n");
}
if (gstruct->watch_dicts()) {
fprintf(f, " virtual void owned_dict_item_set(grt::internal::OwnedDict *dict, const std::string &key);\n");
fprintf(f, " virtual void owned_dict_item_removed(grt::internal::OwnedDict *dict, const std::string &key);\n");
}
// signals
for (auto iter = gstruct->get_signals_partial().begin(); iter != gstruct->get_signals_partial().end(); ++iter) {
fprintf(f, " boost::signals2::signal<void (%s)> _signal_%s;\n", format_signal_args(iter->arg_types).c_str(),
iter->name.c_str());
}
fprintf(f, "\n");
// generate member variables
for (auto iter = members.begin(); iter != members.end(); ++iter) {
if (!iter->second.calculated && !iter->second.overrides)
fprintf(f, " %s _%s;%s\n", format_type_cpp(iter->second.type).c_str(), iter->second.name.c_str(),
iter->second.owned_object ? "// owned" : "");
}
fprintf(f, "\n");
fprintf(f, "private: // Wrapper methods for use by the grt.\n");
if ((needs_body && gstruct->impl_data()) || !gstruct->get_attribute("simple-impl-data").empty()) {
fprintf(f, " ImplData *_data;\n");
if (!gstruct->get_attribute("simple-impl-data").empty())
fprintf(f, " void (*_release_data)(ImplData *);\n");
fprintf(f, "\n");
}
// function to create the object
if (!gstruct->is_abstract()) {
fprintf(f, " static grt::ObjectRef create() {\n");
fprintf(f, " return grt::ObjectRef(new %s());\n", cname.c_str());
fprintf(f, " }\n");
fprintf(f, "\n");
}
// generate method wrappers for grt
for (auto iter = methods.begin(); iter != methods.end(); ++iter) {
if (!iter->second.constructor) {
if (iter->second.ret_type.base.type == UnknownType)
fprintf(f,
" static grt::ValueRef call_%s(grt::internal::Object *self, const grt::BaseListRef &args)"
"{ dynamic_cast<%s*>(self)->%s(%s); return grt::ValueRef(); }\n",
iter->second.name.c_str(), cname.c_str(), iter->second.name.c_str(),
format_wraparg_list(iter->second.arg_types).c_str());
else
fprintf(f,
" static grt::ValueRef call_%s(grt::internal::Object *self, const grt::BaseListRef &args)"
"{ return dynamic_cast<%s*>(self)->%s(%s); }\n",
iter->second.name.c_str(), cname.c_str(), iter->second.name.c_str(),
format_wraparg_list(iter->second.arg_types).c_str());
fprintf(f, "\n");
}
}
// Class registration.
fprintf(f, "public:\n");
fprintf(f, " static void grt_register() {\n");
fprintf(f, " grt::MetaClass *meta = grt::GRT::get()->get_metaclass(static_class_name());\n");
fprintf(f,
" if (meta == nullptr)\n throw std::runtime_error(\"error initializing grt object class, metaclass not found\");\n");
if (gstruct->is_abstract())
fprintf(f, " meta->bind_allocator(nullptr);\n");
else
fprintf(f, " meta->bind_allocator(&%s::create);\n", cname.c_str());
for (std::map<std::string, MetaClass::Member>::const_iterator iter = members.begin(); iter != members.end();
++iter) {
if (iter->second.calculated) {
if (!iter->second.delegate_set)
fprintf(f, " meta->bind_member(\"%s\", new grt::MetaClass::Property<%s,%s>(&%s::%s));\n",
iter->second.name.c_str(), cname.c_str(), format_type_cpp(iter->second.type).c_str(), cname.c_str(),
iter->second.name.c_str());
else {
fprintf(f, " {\n");
fprintf(f, " void (%s::*setter)(const %s &) = &%s::%s%s;\n", cname.c_str(),
format_type_cpp(iter->second.type).c_str(), cname.c_str(), /*iter->second.read_only?"__":*/ "",
iter->second.name.c_str());
fprintf(f, " %s (%s::*getter)() const = &%s::%s;\n", format_type_cpp(iter->second.type).c_str(),
cname.c_str(), cname.c_str(), iter->second.name.c_str());
fprintf(f, " meta->bind_member(\"%s\", new grt::MetaClass::Property<%s,%s>(getter, setter));\n",
iter->second.name.c_str(), cname.c_str(), format_type_cpp(iter->second.type).c_str());
fprintf(f, " }\n");
}
} else {
fprintf(f, " {\n");
if (iter->second.overrides) {
if (iter->second.delegate_set) {
fprintf(f, " void (%s::*setter)(const %s &) = &%s::%s%s;\n", cname.c_str(),
format_type_cpp(iter->second.type).c_str(), cname.c_str(), /*iter->second.read_only?"__":*/ "",
iter->second.name.c_str());
} else {
fprintf(f, " void (%s::*setter)(const %s &) = 0;\n", cname.c_str(),
format_type_cpp(iter->second.type).c_str());
}
} else { // read-only members should still have a setter for unserialization
fprintf(f, " void (%s::*setter)(const %s &) = &%s::%s%s;\n", cname.c_str(),
format_type_cpp(iter->second.type).c_str(), cname.c_str(), /*iter->second.read_only?"__":*/ "",
iter->second.name.c_str());
}
if (iter->second.overrides) {
if (iter->second.delegate_get)
fprintf(f, " %s (%s::*getter)() const = &%s::%s;\n", format_type_cpp(iter->second.type).c_str(),
cname.c_str(), cname.c_str(), iter->second.name.c_str());
else
fprintf(f, " %s (%s::*getter)() const = 0;\n", format_type_cpp(iter->second.type).c_str(),
cname.c_str());
} else {
fprintf(f, " %s (%s::*getter)() const = &%s::%s;\n", format_type_cpp(iter->second.type).c_str(),
cname.c_str(), cname.c_str(), iter->second.name.c_str());
}
fprintf(f, " meta->bind_member(\"%s\", new grt::MetaClass::Property<%s,%s>(getter, setter));\n",
iter->second.name.c_str(), cname.c_str(), format_type_cpp(iter->second.type).c_str());
fprintf(f, " }\n");
}
}
for (std::map<std::string, MetaClass::Method>::const_iterator iter = methods.begin(); iter != methods.end();
++iter) {
fprintf(f, " meta->bind_method(\"%s\", &%s::call_%s);\n", iter->second.name.c_str(), cname.c_str(),
iter->second.name.c_str());
}
fprintf(f, " }\n");
fprintf(f, "};\n\n");
}