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:
@@ -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,\
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user