diff options
author | Stephan Bergmann <stephan.bergmann@allotropia.de> | 2024-01-30 18:09:50 +0100 |
---|---|---|
committer | Stephan Bergmann <stephan.bergmann@allotropia.de> | 2024-01-30 22:38:14 +0100 |
commit | 1b371a4e1fac86fb483a7e62225e130d3684bb59 (patch) | |
tree | a5e34b5ea9c153662020a1a51245ce21043d473e /static/source/embindmaker/embindmaker.cxx | |
parent | 4a806d6b02fcfa795dd4c47932e98f9fbc1b8ca8 (diff) |
embindmaker: Handle new-style services
Change-Id: I41309a20666c17f0c8c8d456943b3c78d0273905
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162772
Tested-by: Jenkins
Reviewed-by: Stephan Bergmann <stephan.bergmann@allotropia.de>
Diffstat (limited to 'static/source/embindmaker/embindmaker.cxx')
-rw-r--r-- | static/source/embindmaker/embindmaker.cxx | 99 |
1 files changed, 79 insertions, 20 deletions
diff --git a/static/source/embindmaker/embindmaker.cxx b/static/source/embindmaker/embindmaker.cxx index 2c707f9f118a..c7aba58c3089 100644 --- a/static/source/embindmaker/embindmaker.cxx +++ b/static/source/embindmaker/embindmaker.cxx @@ -118,11 +118,26 @@ std::pair<OUString, bool> parseRegistryArgument(sal_uInt32 argument) struct Module { std::map<OUString, std::shared_ptr<Module>> modules; - std::vector<OUString> interfaces; + std::vector<std::pair<OUString, OUString>> mappings; }; +OUString +getServiceConstructorName(unoidl::SingleInterfaceBasedServiceEntity::Constructor const& constructor) +{ + return constructor.defaultConstructor ? u"create"_ustr : constructor.name; +} + +OUString jsName(OUString const& name) { return name.replace('.', '$'); } + +OUString +jsServiceConstructor(OUString const& service, + unoidl::SingleInterfaceBasedServiceEntity::Constructor const& constructor) +{ + return "uno_Function_" + jsName(service) + "$$" + getServiceConstructorName(constructor); +} + void scan(rtl::Reference<unoidl::MapCursor> const& cursor, std::u16string_view prefix, - Module* module, std::vector<OUString>& interfaces) + Module* module, std::vector<OUString>& interfaces, std::vector<OUString>& services) { assert(cursor.is()); assert(module != nullptr); @@ -145,13 +160,31 @@ void scan(rtl::Reference<unoidl::MapCursor> const& cursor, std::u16string_view p sub = std::make_shared<Module>(); } scan(static_cast<unoidl::ModuleEntity*>(ent.get())->createCursor(), - Concat2View(name + "."), sub.get(), interfaces); + Concat2View(name + "."), sub.get(), interfaces, services); break; } case unoidl::Entity::SORT_INTERFACE_TYPE: - module->interfaces.emplace_back(name); + module->mappings.emplace_back(id, "uno_Type_" + jsName(name)); interfaces.emplace_back(name); break; + case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE: + { + auto const& ctors + = static_cast<unoidl::SingleInterfaceBasedServiceEntity*>(ent.get()) + ->getConstructors(); + if (!ctors.empty()) + { + auto sub = std::make_shared<Module>(); + for (auto const& ctor : ctors) + { + sub->mappings.emplace_back(getServiceConstructorName(ctor), + jsServiceConstructor(name, ctor)); + } + module->modules[id] = sub; + services.emplace_back(name); + } + } + break; default: break; } @@ -160,8 +193,6 @@ void scan(rtl::Reference<unoidl::MapCursor> const& cursor, std::u16string_view p OUString cppName(OUString const& name) { return "::" + name.replaceAll(u".", u"::"); } -OUString jsName(OUString const& name) { return name.replace('.', '$'); } - OUString resolveOuterTypedefs(rtl::Reference<TypeManager> const& manager, OUString const& name) { for (OUString n(name);;) @@ -529,17 +560,32 @@ void dumpBase(std::ostream& out, rtl::Reference<TypeManager> const& manager, dumpMethods(out, manager, interface, ent, baseTrail); } +void dumpRegisterFunctionProlog(std::ostream& out, unsigned long long& counter) +{ + out << "static void __attribute__((noinline)) register" << counter << "() {\n"; +} + +void dumpRegisterFunctionEpilog(std::ostream& out, unsigned long long& counter) +{ + out << "}\n"; + ++counter; + if (counter == 0) + { + std::cerr << "Emitting too many register functions\n"; + std::exit(EXIT_FAILURE); + } +} + void writeJsMap(std::ostream& out, Module const& module, std::string const& prefix) { auto comma = false; - for (auto const& ifc : module.interfaces) + for (auto const & [ id, to ] : module.mappings) { if (comma) { out << ",\n"; } - out << prefix << "'" << ifc.copy(ifc.lastIndexOf('.') + 1) << "': instance.uno_Type_" - << jsName(ifc); + out << prefix << "'" << id << "': instance." << to; comma = true; } for (auto const & [ id, sub ] : module.modules) @@ -589,9 +635,10 @@ SAL_IMPLEMENT_MAIN() } auto const module = std::make_shared<Module>(); std::vector<OUString> interfaces; + std::vector<OUString> services; for (auto const& prov : mgr->getPrimaryProviders()) { - scan(prov->createRootCursor(), u"", module.get(), interfaces); + scan(prov->createRootCursor(), u"", module.get(), interfaces, services); } std::ofstream cppOut(cppPathname, std::ios_base::out | std::ios_base::trunc); if (!cppOut) @@ -607,6 +654,10 @@ SAL_IMPLEMENT_MAIN() { cppOut << "#include <" << ifc.replace('.', '/') << ".hpp>\n"; } + for (auto const& srv : services) + { + cppOut << "#include <" << srv.replace('.', '/') << ".hpp>\n"; + } cppOut << "\n" "// TODO: This is a temporary workaround that likely causes the Embind UNO\n" "// bindings to leak memory. Reference counting and cloning mechanisms of\n" @@ -625,10 +676,8 @@ SAL_IMPLEMENT_MAIN() assert(ent.is()); assert(ent->getSort() == unoidl::Entity::SORT_INTERFACE_TYPE); rtl::Reference const ifcEnt(static_cast<unoidl::InterfaceTypeEntity*>(ent.get())); - cppOut << "static void __attribute__((noinline)) register" << n - << "() {\n" - " ::emscripten::class_<" - << cppName(ifc); + dumpRegisterFunctionProlog(cppOut, n); + cppOut << " ::emscripten::class_<" << cppName(ifc); //TODO: Embind only supports single inheritance, so use that support at least for a UNO // interface's first base, and explicitly spell out the attributes and methods of any // remaining bases: @@ -671,14 +720,24 @@ SAL_IMPLEMENT_MAIN() } dumpAttributes(cppOut, mgr, ifc, ifcEnt, {}); dumpMethods(cppOut, mgr, ifc, ifcEnt, {}); - cppOut << " ;\n" - "}\n"; - ++n; - if (n == 0) + cppOut << " ;\n"; + dumpRegisterFunctionEpilog(cppOut, n); + } + for (auto const& srv : services) + { + auto const ent = mgr->getManager()->findEntity(srv); + assert(ent.is()); + assert(ent->getSort() == unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE); + rtl::Reference const srvEnt( + static_cast<unoidl::SingleInterfaceBasedServiceEntity*>(ent.get())); + dumpRegisterFunctionProlog(cppOut, n); + for (auto const& ctor : srvEnt->getConstructors()) { - std::cerr << "Emitting too many register functions\n"; - std::exit(EXIT_FAILURE); + cppOut << " ::emscripten::function(\"" << jsServiceConstructor(srv, ctor) + << "\", &" << cppName(srv) << "::" << getServiceConstructorName(ctor) + << ");\n"; } + dumpRegisterFunctionEpilog(cppOut, n); } cppOut << "EMSCRIPTEN_BINDINGS(unoembind_" << name << ") {\n"; for (unsigned long long i = 0; i != n; ++i) |