Let embindmaker also generate a .js file with more natural names

(i.e., Module.unoembind_uno.com.sun.star... vs. Module.com$sun$star$..., and see
the updated examples in static/README.wasm.md for further shortening that to
just css...)

Change-Id: I6dc079caa8c93a4042a6a8aa2d8fcc8f76bf80f3
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162580
Tested-by: Jenkins
Reviewed-by: Stephan Bergmann <stephan.bergmann@allotropia.de>
This commit is contained in:
Stephan Bergmann
2024-01-25 18:31:42 +01:00
parent c479944eb4
commit cbae6e581a
6 changed files with 260 additions and 123 deletions
+1
View File
@@ -1036,6 +1036,7 @@ $(eval $(call gb_Helper_register_packages_for_install,ooo,\
) \
resource_fonts \
cui \
$(if $(filter EMSCRIPTEN,$(OS)),unoembind) \
))
$(eval $(call gb_Helper_register_packages_for_install,ooo_fonts,\
+7 -3
View File
@@ -11,12 +11,16 @@ $(eval $(call gb_CustomTarget_CustomTarget,static/unoembind))
$(eval $(call gb_CustomTarget_register_targets,static/unoembind, \
bindings_uno.cxx \
bindings_uno.js \
))
$(call gb_CustomTarget_get_workdir,static/unoembind)/bindings_uno.cxx: \
$(call gb_CustomTarget_get_workdir,static/unoembind)/bindings_uno.cxx \
$(call gb_CustomTarget_get_workdir,static/unoembind)/bindings_uno.js: \
$(call gb_Executable_get_target_for_build,embindmaker) $(call gb_UnoApi_get_target,udkapi) \
$(call gb_UnoApi_get_target,offapi)
$(call gb_Executable_get_command,embindmaker) uno +$(call gb_UnoApi_get_target,udkapi) \
+$(call gb_UnoApi_get_target,offapi) > $@
$(call gb_Executable_get_command,embindmaker) uno \
$(call gb_CustomTarget_get_workdir,static/unoembind)/bindings_uno.cxx \
$(call gb_CustomTarget_get_workdir,static/unoembind)/bindings_uno.js \
+$(call gb_UnoApi_get_target,udkapi) +$(call gb_UnoApi_get_target,offapi)
# vim: set noet sw=4 ts=4:
+1
View File
@@ -19,6 +19,7 @@ ifeq (EMSCRIPTEN,$(OS))
$(eval $(call gb_Module_add_targets,static,\
CustomTarget_emscripten_fs_image \
CustomTarget_unoembind \
Package_unoembind \
StaticLibrary_unoembind \
$(if $(ENABLE_QT5), \
CustomTarget_wasm-qt5-mandelbrot_moc \
+18
View File
@@ -0,0 +1,18 @@
# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t; fill-column: 100 -*-
#
# This file is part of the LibreOffice project.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
$(eval $(call gb_Package_Package,unoembind,$(call gb_CustomTarget_get_workdir,static/unoembind)))
$(eval $(call gb_Package_use_custom_target,unoembind,static/unoembind))
$(eval $(call gb_Package_add_files,unoembind,$(LIBO_BIN_FOLDER), \
bindings_uno.js \
))
# vim: set noet sw=4 ts=4:
+11 -7
View File
@@ -223,29 +223,33 @@ improvement! ;)
Some usage examples through javascript of the current implementation:
```js
// inserts a string at the start of the Writer document.
Module.init_unoembind_uno();
let css = Module.unoembind_uno.com.sun.star;
xModel = Module.getCurrentModelFromViewSh();
xTextDocument = new Module.com$sun$star$text$XTextDocumentRef(xModel, Module.UnoReference_Query.UNO_QUERY);
xTextDocument = new css.text.XTextDocument(xModel, Module.UnoReference_Query.UNO_QUERY);
xText = xTextDocument.getText();
xSimpleText = new Module.com$sun$star$text$XSimpleTextRef(xText, Module.UnoReference_Query.UNO_QUERY);
xSimpleText = new css.text.XSimpleText(xText, Module.UnoReference_Query.UNO_QUERY);
xTextCursor = xSimpleText.createTextCursor();
xTextRange = new Module.com$sun$star$text$XTextRangeRef(xTextCursor, Module.UnoReference_Query.UNO_QUERY);
xTextRange = new css.text.XTextRange(xTextCursor, Module.UnoReference_Query.UNO_QUERY);
xTextRange.setString(new Module.OUString("string here!"));
xModel.delete(); xTextDocument.delete(); xText.delete(); xSimpleText.delete(); xTextCursor.delete(); xTextRange.delete();
```
```js
// changes each paragraph of the Writer document to a random color.
Module.init_unoembind_uno();
let css = Module.unoembind_uno.com.sun.star;
xModel = Module.getCurrentModelFromViewSh();
xTextDocument = new Module.com$sun$star$text$XTextDocumentRef(xModel, Module.UnoReference_Query.UNO_QUERY);
xTextDocument = new css.text.XTextDocument(xModel, Module.UnoReference_Query.UNO_QUERY);
xText = xTextDocument.getText();
xEnumAccess = new Module.com$sun$star$container$XEnumerationAccessRef(xText, Module.UnoReference_Query.UNO_QUERY);
xEnumAccess = new css.container.XEnumerationAccess(xText, Module.UnoReference_Query.UNO_QUERY);
xParaEnumeration = xEnumAccess.createEnumeration();
while (xParaEnumeration.hasMoreElements()) {
xParagraph = new Module.com$sun$star$text$XTextRangeRef();
xParagraph = new css.text.XTextRange();
xParagraph.set(xParaEnumeration.nextElement(), Module.UnoReference_Query.UNO_QUERY);
if (xParagraph.is()) {
xParaProps = new Module.com$sun$star$beans$XPropertySetRef(xParagraph, Module.UnoReference_Query.UNO_QUERY);
xParaProps = new css.beans.XPropertySet(xParagraph, Module.UnoReference_Query.UNO_QUERY);
xParaProps.setPropertyValue(new Module.OUString("CharColor"), new Module.Any(Math.floor(Math.random() * 0xFFFFFF), Module.UnoType.long));
}
}
+222 -113
View File
@@ -11,7 +11,13 @@
#include <cassert>
#include <cstdlib>
#include <fstream>
#include <ios>
#include <iostream>
#include <map>
#include <memory>
#include <ostream>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
@@ -20,9 +26,11 @@
#include <codemaker/typemanager.hxx>
#include <osl/file.hxx>
#include <osl/process.h>
#include <osl/thread.h>
#include <rtl/process.h>
#include <rtl/ref.hxx>
#include <rtl/string.hxx>
#include <rtl/textcvt.h>
#include <rtl/ustrbuf.hxx>
#include <rtl/ustring.hxx>
#include <sal/main.h>
@@ -35,14 +43,32 @@ void badUsage()
{
std::cerr
<< "Usage:\n\n"
" embindmaker <prefix> <registries>\n\n"
" embindmaker <name> <cpp-ouptput> <js-output> <registries>\n\n"
"where each <registry> is '+' (primary) or ':' (secondary), followed by: either a\n"
"new- or legacy-format .rdb file, a single .idl file, or a root directory of an\n"
".idl file tree. Embind code for all primary registries is written to stdout,"
"with <prefix> used as part of the name passed to EMSCRIPTEN_BINDINGS.\n";
".idl file tree. For all primary registries, Embind code is written to\n"
"<cpp-output> and corresponding JavaScript scaffolding code is written to\n"
"<js-output>. The <name> is used as part of some of the identifiers in those\n"
"generated files.\n";
std::exit(EXIT_FAILURE);
}
std::string getPathnameArgument(sal_uInt32 argument)
{
OUString arg;
rtl_getAppCommandArg(argument, &arg.pData);
OString path;
auto const enc = osl_getThreadTextEncoding();
if (!arg.convertToString(&path, enc,
RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
| RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR))
{
std::cerr << "Cannot convert \"" << arg << "\" to system encoding " << enc << "\n";
std::exit(EXIT_FAILURE);
}
return std::string(path);
}
std::pair<OUString, bool> parseRegistryArgument(sal_uInt32 argument)
{
OUString arg;
@@ -86,10 +112,17 @@ std::pair<OUString, bool> parseRegistryArgument(sal_uInt32 argument)
return { abs, primary };
}
struct Module
{
std::map<OUString, std::shared_ptr<Module>> modules;
std::vector<OUString> interfaces;
};
void scan(rtl::Reference<unoidl::MapCursor> const& cursor, std::u16string_view prefix,
std::vector<OUString>& interfaces)
Module* module, std::vector<OUString>& interfaces)
{
assert(cursor.is());
assert(module != nullptr);
for (;;)
{
OUString id;
@@ -102,10 +135,18 @@ void scan(rtl::Reference<unoidl::MapCursor> const& cursor, std::u16string_view p
switch (ent->getSort())
{
case unoidl::Entity::SORT_MODULE:
{
auto& sub = module->modules[id];
if (!sub)
{
sub = std::make_shared<Module>();
}
scan(static_cast<unoidl::ModuleEntity*>(ent.get())->createCursor(),
Concat2View(name + "."), interfaces);
Concat2View(name + "."), sub.get(), interfaces);
break;
}
case unoidl::Entity::SORT_INTERFACE_TYPE:
module->interfaces.emplace_back(name);
interfaces.emplace_back(name);
break;
default:
@@ -118,16 +159,17 @@ OUString cppName(OUString const& name) { return "::" + name.replaceAll(u".", u":
OUString jsName(OUString const& name) { return name.replace('.', '$'); }
void dumpAttributes(OUString const& name, rtl::Reference<unoidl::InterfaceTypeEntity> const& entity)
void dumpAttributes(std::ostream& out, OUString const& name,
rtl::Reference<unoidl::InterfaceTypeEntity> const& entity)
{
for (auto const& attr : entity->getDirectAttributes())
{
std::cout << " .function(\"get" << attr.name << "\", &" << cppName(name) << "::get"
<< attr.name << ")\n";
out << " .function(\"get" << attr.name << "\", &" << cppName(name) << "::get"
<< attr.name << ")\n";
if (!attr.readOnly)
{
std::cout << " .function(\"set" << attr.name << "\", &" << cppName(name)
<< "::set" << attr.name << ")\n";
out << " .function(\"set" << attr.name << "\", &" << cppName(name) << "::set"
<< attr.name << ")\n";
}
}
}
@@ -201,7 +243,8 @@ bool passByReference(rtl::Reference<TypeManager> const& manager, OUString const&
}
}
void dumpType(rtl::Reference<TypeManager> const& manager, std::u16string_view name, bool isConst)
void dumpType(std::ostream& out, rtl::Reference<TypeManager> const& manager,
std::u16string_view name, bool isConst)
{
sal_Int32 k;
std::vector<OString> args;
@@ -209,69 +252,69 @@ void dumpType(rtl::Reference<TypeManager> const& manager, std::u16string_view na
b2u(codemaker::UnoType::decompose(u2b(resolveAllTypedefs(manager, name)), &k, &args)));
if (isConst)
{
std::cout << "const ";
out << "const ";
}
for (sal_Int32 i = 0; i != k; ++i)
{
std::cout << "::css::uno::Sequence<";
out << "::css::uno::Sequence<";
}
switch (manager->getSort(n))
{
case codemaker::UnoType::Sort::Void:
std::cout << "void";
out << "void";
break;
case codemaker::UnoType::Sort::Boolean:
std::cout << "::sal_Bool";
out << "::sal_Bool";
break;
case codemaker::UnoType::Sort::Byte:
std::cout << "::sal_Int8";
out << "::sal_Int8";
break;
case codemaker::UnoType::Sort::Short:
std::cout << "::sal_Int16";
out << "::sal_Int16";
break;
case codemaker::UnoType::Sort::UnsignedShort:
std::cout << "::sal_uInt16";
out << "::sal_uInt16";
break;
case codemaker::UnoType::Sort::Long:
std::cout << "::sal_Int32";
out << "::sal_Int32";
break;
case codemaker::UnoType::Sort::UnsignedLong:
std::cout << "::sal_uInt32";
out << "::sal_uInt32";
break;
case codemaker::UnoType::Sort::Hyper:
std::cout << "::sal_Int64";
out << "::sal_Int64";
break;
case codemaker::UnoType::Sort::UnsignedHyper:
std::cout << "::sal_uInt64";
out << "::sal_uInt64";
break;
case codemaker::UnoType::Sort::Float:
std::cout << "float";
out << "float";
break;
case codemaker::UnoType::Sort::Double:
std::cout << "double";
out << "double";
break;
case codemaker::UnoType::Sort::Char:
std::cout << "::sal_Unicode";
out << "::sal_Unicode";
break;
case codemaker::UnoType::Sort::String:
std::cout << "::rtl::OUString";
out << "::rtl::OUString";
break;
case codemaker::UnoType::Sort::Type:
std::cout << "::css::uno::Type";
out << "::css::uno::Type";
break;
case codemaker::UnoType::Sort::Any:
std::cout << "::css::uno::Any";
out << "::css::uno::Any";
break;
case codemaker::UnoType::Sort::Enum:
case codemaker::UnoType::Sort::PlainStruct:
case codemaker::UnoType::Sort::Exception:
std::cout << cppName(n);
out << cppName(n);
break;
case codemaker::UnoType::Sort::PolymorphicStructTemplate:
std::cout << cppName(n);
out << cppName(n);
if (!args.empty())
{
std::cout << "<";
out << "<";
bool first = true;
for (auto const& arg : args)
{
@@ -281,17 +324,17 @@ void dumpType(rtl::Reference<TypeManager> const& manager, std::u16string_view na
}
else
{
std::cout << ", ";
out << ", ";
}
dumpType(manager, b2u(arg), false);
dumpType(out, manager, b2u(arg), false);
}
std::cout << ">";
out << ">";
}
break;
case codemaker::UnoType::Sort::Interface:
std::cout << "::css::uno::Reference<";
std::cout << cppName(n);
std::cout << ">";
out << "::css::uno::Reference<";
out << cppName(n);
out << ">";
break;
default:
throw CannotDumpException(OUString::Concat("unexpected entity \"") + name
@@ -299,11 +342,11 @@ void dumpType(rtl::Reference<TypeManager> const& manager, std::u16string_view na
}
for (sal_Int32 i = 0; i != k; ++i)
{
std::cout << ">";
out << ">";
}
}
void dumpParameters(rtl::Reference<TypeManager> const& manager,
void dumpParameters(std::ostream& out, rtl::Reference<TypeManager> const& manager,
unoidl::InterfaceTypeEntity::Method const& method, bool declarations)
{
bool first = true;
@@ -315,7 +358,7 @@ void dumpParameters(rtl::Reference<TypeManager> const& manager,
}
else
{
std::cout << ", ";
out << ", ";
}
bool isConst;
bool isRef;
@@ -332,58 +375,60 @@ void dumpParameters(rtl::Reference<TypeManager> const& manager,
// For the embind wrapper, we define a pointer instead of a reference:
if (declarations)
{
dumpType(manager, param.type, isConst);
std::cout << " ";
dumpType(out, manager, param.type, isConst);
out << " ";
}
if (isRef)
{
std::cout << "*";
out << "*";
}
if (declarations)
{
std::cout << " ";
out << " ";
}
std::cout << param.name;
out << param.name;
}
}
void dumpWrapper(rtl::Reference<TypeManager> const& manager, OUString const& interfaceName,
unoidl::InterfaceTypeEntity::Method const& method, bool forReference)
void dumpWrapper(std::ostream& out, rtl::Reference<TypeManager> const& manager,
OUString const& interfaceName, unoidl::InterfaceTypeEntity::Method const& method,
bool forReference)
{
std::cout << " .function(\"" << method.name << "\", +[](";
out << " .function(\"" << method.name << "\", +[](";
if (forReference)
{
std::cout << "::com::sun::star::uno::Reference<";
out << "::com::sun::star::uno::Reference<";
}
std::cout << cppName(interfaceName);
out << cppName(interfaceName);
if (forReference)
{
std::cout << ">";
out << ">";
}
std::cout << " * the_self";
out << " * the_self";
if (!method.parameters.empty())
{
std::cout << ", ";
out << ", ";
}
dumpParameters(manager, method, true);
std::cout << ") { return the_self->";
dumpParameters(out, manager, method, true);
out << ") { return the_self->";
if (forReference)
{
std::cout << "get()->";
out << "get()->";
}
std::cout << method.name << "(";
dumpParameters(manager, method, false);
std::cout << "); }, ::emscripten::allow_raw_pointers())\n";
out << method.name << "(";
dumpParameters(out, manager, method, false);
out << "); }, ::emscripten::allow_raw_pointers())\n";
}
void dumpMethods(rtl::Reference<TypeManager> const& manager, OUString const& name,
rtl::Reference<unoidl::InterfaceTypeEntity> const& entity, bool forReference)
void dumpMethods(std::ostream& out, rtl::Reference<TypeManager> const& manager,
OUString const& name, rtl::Reference<unoidl::InterfaceTypeEntity> const& entity,
bool forReference)
{
for (auto const& meth : entity->getDirectMethods())
{
if (forReference)
{
dumpWrapper(manager, name, meth, true);
dumpWrapper(out, manager, name, meth, true);
}
else if (std::any_of(
meth.parameters.begin(), meth.parameters.end(), [](auto const& parameter) {
@@ -391,15 +436,45 @@ void dumpMethods(rtl::Reference<TypeManager> const& manager, OUString const& nam
!= unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN;
}))
{
dumpWrapper(manager, name, meth, false);
dumpWrapper(out, manager, name, meth, false);
}
else
{
std::cout << " .function(\"" << meth.name << "\", &" << cppName(name)
<< "::" << meth.name << ")\n";
out << " .function(\"" << meth.name << "\", &" << cppName(name)
<< "::" << meth.name << ")\n";
}
}
}
void writeJsMap(std::ostream& out, Module const& module, std::string const& prefix)
{
auto comma = false;
for (auto const& ifc : module.interfaces)
{
if (comma)
{
out << ",\n";
}
out << prefix << "'" << ifc.copy(ifc.lastIndexOf('.') + 1) << "': Module." << jsName(ifc)
<< "Ref";
comma = true;
}
for (auto const & [ id, sub ] : module.modules)
{
if (comma)
{
out << ",\n";
}
out << prefix << "'" << id << "': {\n";
writeJsMap(out, *sub, prefix + " ");
out << prefix << "}";
comma = true;
}
if (comma)
{
out << "\n";
}
}
}
SAL_IMPLEMENT_MAIN()
@@ -407,14 +482,16 @@ SAL_IMPLEMENT_MAIN()
try
{
auto const args = rtl_getAppCommandArgCount();
if (args == 0)
if (args < 3)
{
badUsage();
}
OUString prefix;
rtl_getAppCommandArg(0, &prefix.pData);
OUString name;
rtl_getAppCommandArg(0, &name.pData);
auto const cppPathname = getPathnameArgument(1);
auto const jsPathname = getPathnameArgument(2);
rtl::Reference<TypeManager> mgr(new TypeManager);
for (sal_uInt32 i = 1; i != args; ++i)
for (sal_uInt32 i = 3; i != args; ++i)
{
auto const & [ uri, primary ] = parseRegistryArgument(i);
try
@@ -427,67 +504,99 @@ SAL_IMPLEMENT_MAIN()
std::exit(EXIT_FAILURE);
}
}
auto const module = std::make_shared<Module>();
std::vector<OUString> interfaces;
for (auto const& prov : mgr->getPrimaryProviders())
{
scan(prov->createRootCursor(), u"", interfaces);
scan(prov->createRootCursor(), u"", module.get(), interfaces);
}
std::cout << "#include <emscripten/bind.h>\n"
"#include <com/sun/star/uno/Any.hxx>\n"
"#include <com/sun/star/uno/Reference.hxx>\n";
std::ofstream cppOut(cppPathname, std::ios_base::out | std::ios_base::trunc);
if (!cppOut)
{
std::cerr << "Cannot open \"" << cppPathname << "\" for writing\n";
std::exit(EXIT_FAILURE);
}
cppOut << "#include <emscripten/bind.h>\n"
"#include <com/sun/star/uno/Any.hxx>\n"
"#include <com/sun/star/uno/Reference.hxx>\n";
for (auto const& ifc : interfaces)
{
std::cout << "#include <" << ifc.replace('.', '/') << ".hpp>\n";
cppOut << "#include <" << ifc.replace('.', '/') << ".hpp>\n";
}
std::cout << "\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"
"// Embind should be investigated to figure out what exactly we need here:\n"
"namespace emscripten::internal {\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"
"// Embind should be investigated to figure out what exactly we need here:\n"
"namespace emscripten::internal {\n";
for (auto const& ifc : interfaces)
{
std::cout << " template<> void raw_destructor<" << cppName(ifc) << ">("
<< cppName(ifc) << " *) {}\n";
cppOut << " template<> void raw_destructor<" << cppName(ifc) << ">(" << cppName(ifc)
<< " *) {}\n";
}
std::cout << "}\n\n"
"EMSCRIPTEN_BINDINGS(uno_bindings_"
<< prefix << ") {\n";
cppOut << "}\n\n"
"EMSCRIPTEN_BINDINGS(unoembind_"
<< name << ") {\n";
for (auto const& ifc : interfaces)
{
auto const ent = mgr->getManager()->findEntity(ifc);
assert(ent.is());
assert(ent->getSort() == unoidl::Entity::SORT_INTERFACE_TYPE);
rtl::Reference const ifcEnt(static_cast<unoidl::InterfaceTypeEntity*>(ent.get()));
std::cout << " ::emscripten::class_<" << cppName(ifc) << ">(\"" << jsName(ifc)
<< "\")\n";
dumpAttributes(ifc, ifcEnt);
dumpMethods(mgr, ifc, ifcEnt, false);
std::cout << " ;\n"
" ::emscripten::class_<::com::sun::star::uno::Reference<"
<< cppName(ifc)
<< ">, ::emscripten::base<::com::sun::star::uno::BaseReference>>(\""
<< jsName(ifc)
<< "Ref\")\n"
" .constructor<>()\n"
" .constructor<::com::sun::star::uno::BaseReference, "
"::com::sun::star::uno::UnoReference_Query>()\n"
" .function(\"is\", &::com::sun::star::uno::Reference<"
<< cppName(ifc)
<< ">::is)\n"
" .function(\"get\", &::com::sun::star::uno::Reference<"
<< cppName(ifc)
<< ">::get, ::emscripten::allow_raw_pointers())\n"
" .function(\"set\", "
"::emscripten::select_overload<bool(::com::sun::star::uno::Any const "
"&, "
"com::sun::star::uno::UnoReference_Query)>(&::com::sun::star::uno::"
"Reference<"
<< cppName(ifc) << ">::set))\n";
dumpAttributes(ifc, ifcEnt);
dumpMethods(mgr, ifc, ifcEnt, true);
std::cout << " ;\n";
cppOut << " ::emscripten::class_<" << cppName(ifc) << ">(\"" << jsName(ifc)
<< "\")\n";
dumpAttributes(cppOut, ifc, ifcEnt);
dumpMethods(cppOut, mgr, ifc, ifcEnt, false);
cppOut << " ;\n"
" ::emscripten::class_<::com::sun::star::uno::Reference<"
<< cppName(ifc)
<< ">, ::emscripten::base<::com::sun::star::uno::BaseReference>>(\""
<< jsName(ifc)
<< "Ref\")\n"
" .constructor<>()\n"
" .constructor<::com::sun::star::uno::BaseReference, "
"::com::sun::star::uno::UnoReference_Query>()\n"
" .function(\"is\", &::com::sun::star::uno::Reference<"
<< cppName(ifc)
<< ">::is)\n"
" .function(\"get\", &::com::sun::star::uno::Reference<"
<< cppName(ifc)
<< ">::get, ::emscripten::allow_raw_pointers())\n"
" .function(\"set\", "
"::emscripten::select_overload<bool(::com::sun::star::uno::Any const "
"&, "
"com::sun::star::uno::UnoReference_Query)>(&::com::sun::star::uno::"
"Reference<"
<< cppName(ifc) << ">::set))\n";
dumpAttributes(cppOut, ifc, ifcEnt);
dumpMethods(cppOut, mgr, ifc, ifcEnt, true);
cppOut << " ;\n";
}
cppOut << "}\n";
cppOut.close();
if (!cppOut)
{
std::cerr << "Failed to write \"" << cppPathname << "\"\n";
std::exit(EXIT_FAILURE);
}
std::ofstream jsOut(jsPathname, std::ios_base::out | std::ios_base::trunc);
if (!jsOut)
{
std::cerr << "Cannot open \"" << jsPathname << "\" for writing\n";
std::exit(EXIT_FAILURE);
}
jsOut << "Module.init_unoembind_" << name
<< " = function() {\n"
" Module.unoembind_"
<< name << " = {\n";
writeJsMap(jsOut, *module, " ");
jsOut << " };\n"
"};\n";
jsOut.close();
if (!jsOut)
{
std::cerr << "Failed to write \"" << jsPathname << "\"\n";
std::exit(EXIT_FAILURE);
}
std::cout << "}\n";
return EXIT_SUCCESS;
}
catch (unoidl::FileFormatException const& e)