Rework the Embind mapping of UNO interfaces

...to make use of the automatic finalization clean-up of smart pointers
available with recent versions of Embind (so that explicitly calling delete() on
them should largely be optional now).  See the changes to static/README.wasm.md
for how code should look like now.  (The Module.uno_Reference.FromAny dummy
argument for the interface constructor converting from an Any is only necessary
to distinguish it from the other constructor, as otherwise Embind complains
because:  "Overload resolution is currently only performed using the parameter
count, not actual type info!")

Change-Id: Ia8a8c12e38af1093948bf8a20ecd31aa6591e912
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/162697
Tested-by: Jenkins
Reviewed-by: Stephan Bergmann <stephan.bergmann@allotropia.de>
This commit is contained in:
Stephan Bergmann 2024-01-29 15:57:30 +01:00
parent 2df1dcc324
commit 27ceca1996
4 changed files with 85 additions and 70 deletions

View File

@ -0,0 +1,37 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 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/.
*/
#pragma once
#include <sal/config.h>
#include <emscripten/bind.h>
#include <com/sun/star/uno/Reference.hxx>
#include <sal/types.h>
template <typename T> struct emscripten::smart_ptr_trait<css::uno::Reference<T>>
{
using PointerType = css::uno::Reference<T>;
using element_type = T;
static T* get(css::uno::Reference<T> const& ptr) { return ptr.get(); }
static sharing_policy get_sharing_policy() { return sharing_policy::INTRUSIVE; }
static css::uno::Reference<T>* share(T* v) { return new css::uno::Reference<T>(v); }
static css::uno::Reference<T>* construct_null() { return new css::uno::Reference<T>(); }
};
namespace unoembindhelpers
{
enum class uno_Reference
{
FromAny
};
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */

View File

@ -226,12 +226,13 @@ Some usage examples through javascript of the current implementation:
init_unoembind_uno(Module); init_unoembind_uno(Module);
let css = Module.unoembind_uno.com.sun.star; let css = Module.unoembind_uno.com.sun.star;
xModel = Module.getCurrentModelFromViewSh(); xModel = Module.getCurrentModelFromViewSh();
xTextDocument = new css.text.XTextDocument(xModel, Module.UnoReference_Query.UNO_QUERY); xTextDocument = new css.text.XTextDocument(xModel.$query());
xText = xTextDocument.getText(); xText = xTextDocument.getText();
xSimpleText = new css.text.XSimpleText(xText, Module.UnoReference_Query.UNO_QUERY); xSimpleText = new css.text.XSimpleText(xText.$query());
xTextCursor = xSimpleText.createTextCursor(); xTextCursor = xSimpleText.createTextCursor();
xTextRange = new css.text.XTextRange(xTextCursor, Module.UnoReference_Query.UNO_QUERY); xTextRange = new css.text.XTextRange(xTextCursor.$query());
xTextRange.setString(new Module.OUString("string here!")); xTextRange.setString(new Module.OUString("string here!"));
xSimpleText.delete(); xTextCursor.delete(); xTextRange.delete();
xModel.delete(); xTextDocument.delete(); xText.delete(); xSimpleText.delete(); xTextCursor.delete(); xTextRange.delete(); xModel.delete(); xTextDocument.delete(); xText.delete(); xSimpleText.delete(); xTextCursor.delete(); xTextRange.delete();
``` ```
@ -240,16 +241,14 @@ xModel.delete(); xTextDocument.delete(); xText.delete(); xSimpleText.delete(); x
init_unoembind_uno(Module); init_unoembind_uno(Module);
let css = Module.unoembind_uno.com.sun.star; let css = Module.unoembind_uno.com.sun.star;
xModel = Module.getCurrentModelFromViewSh(); xModel = Module.getCurrentModelFromViewSh();
xTextDocument = new css.text.XTextDocument(xModel, Module.UnoReference_Query.UNO_QUERY); init_unoembind_uno(Module);
xText = xTextDocument.getText(); xEnumAccess = new css.container.XEnumerationAccess(xText.$query());
xEnumAccess = new css.container.XEnumerationAccess(xText, Module.UnoReference_Query.UNO_QUERY);
xParaEnumeration = xEnumAccess.createEnumeration(); xParaEnumeration = xEnumAccess.createEnumeration();
while (xParaEnumeration.hasMoreElements()) { while (xParaEnumeration.hasMoreElements()) {
xParagraph = new css.text.XTextRange(); xParagraph = new css.text.XTextRange(xParaEnumeration.nextElement(), Module.uno_Reference.FromAny);
xParagraph.set(xParaEnumeration.nextElement(), Module.UnoReference_Query.UNO_QUERY); if (xParagraph.$is()) {
if (xParagraph.is()) { xParaProps = new css.beans.XPropertySet(xParagraph.$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)); xParaProps.setPropertyValue(new Module.OUString("CharColor"), new Module.Any(Math.floor(Math.random() * 0xFFFFFF), Module.UnoType.long));
} }
} }

View File

@ -391,52 +391,31 @@ void dumpParameters(std::ostream& out, rtl::Reference<TypeManager> const& manage
} }
void dumpWrapper(std::ostream& out, rtl::Reference<TypeManager> const& manager, void dumpWrapper(std::ostream& out, rtl::Reference<TypeManager> const& manager,
OUString const& interfaceName, unoidl::InterfaceTypeEntity::Method const& method, OUString const& interfaceName, unoidl::InterfaceTypeEntity::Method const& method)
bool forReference)
{ {
out << " .function(\"" << method.name << "\", +[]("; out << " .function(\"" << method.name << "\", +[](" << cppName(interfaceName);
if (forReference)
{
out << "::com::sun::star::uno::Reference<";
}
out << cppName(interfaceName);
if (forReference)
{
out << ">";
}
out << " * the_self"; out << " * the_self";
if (!method.parameters.empty()) if (!method.parameters.empty())
{ {
out << ", "; out << ", ";
} }
dumpParameters(out, manager, method, true); dumpParameters(out, manager, method, true);
out << ") { return the_self->"; out << ") { return the_self->" << method.name << "(";
if (forReference)
{
out << "get()->";
}
out << method.name << "(";
dumpParameters(out, manager, method, false); dumpParameters(out, manager, method, false);
out << "); }, ::emscripten::allow_raw_pointers())\n"; out << "); }, ::emscripten::allow_raw_pointers())\n";
} }
void dumpMethods(std::ostream& out, rtl::Reference<TypeManager> const& manager, void dumpMethods(std::ostream& out, rtl::Reference<TypeManager> const& manager,
OUString const& name, rtl::Reference<unoidl::InterfaceTypeEntity> const& entity, OUString const& name, rtl::Reference<unoidl::InterfaceTypeEntity> const& entity)
bool forReference)
{ {
for (auto const& meth : entity->getDirectMethods()) for (auto const& meth : entity->getDirectMethods())
{ {
if (forReference) if (std::any_of(meth.parameters.begin(), meth.parameters.end(), [](auto const& parameter) {
{
dumpWrapper(out, manager, name, meth, true);
}
else if (std::any_of(
meth.parameters.begin(), meth.parameters.end(), [](auto const& parameter) {
return parameter.direction return parameter.direction
!= unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN; != unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN;
})) }))
{ {
dumpWrapper(out, manager, name, meth, false); dumpWrapper(out, manager, name, meth);
} }
else else
{ {
@ -455,7 +434,7 @@ void writeJsMap(std::ostream& out, Module const& module, std::string const& pref
{ {
out << ",\n"; out << ",\n";
} }
out << prefix << "'" << ifc.copy(ifc.lastIndexOf('.') + 1) << "': instance.uno_Reference_" out << prefix << "'" << ifc.copy(ifc.lastIndexOf('.') + 1) << "': instance.uno_Type_"
<< jsName(ifc); << jsName(ifc);
comma = true; comma = true;
} }
@ -518,7 +497,8 @@ SAL_IMPLEMENT_MAIN()
} }
cppOut << "#include <emscripten/bind.h>\n" cppOut << "#include <emscripten/bind.h>\n"
"#include <com/sun/star/uno/Any.hxx>\n" "#include <com/sun/star/uno/Any.hxx>\n"
"#include <com/sun/star/uno/Reference.hxx>\n"; "#include <com/sun/star/uno/Reference.hxx>\n"
"#include <static/unoembindhelpers/PrimaryBindings.hxx>\n";
for (auto const& ifc : interfaces) for (auto const& ifc : interfaces)
{ {
cppOut << "#include <" << ifc.replace('.', '/') << ".hpp>\n"; cppOut << "#include <" << ifc.replace('.', '/') << ".hpp>\n";
@ -544,33 +524,31 @@ SAL_IMPLEMENT_MAIN()
cppOut << "static void __attribute__((noinline)) register" << n cppOut << "static void __attribute__((noinline)) register" << n
<< "() {\n" << "() {\n"
" ::emscripten::class_<" " ::emscripten::class_<"
<< cppName(ifc) << ">(\"uno_Type_" << jsName(ifc) << "\")\n"; << cppName(ifc) << ">(\"uno_Type_" << jsName(ifc)
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>>(\"uno_Reference_"
<< jsName(ifc)
<< "\")\n" << "\")\n"
" .constructor<>()\n" " .smart_ptr<::com::sun::star::uno::Reference<"
" .constructor<::com::sun::star::uno::BaseReference, " << cppName(ifc) << ">>(\"uno_Reference_" << jsName(ifc)
"::com::sun::star::uno::UnoReference_Query>()\n" << "\")\n"
" .function(\"is\", &::com::sun::star::uno::Reference<" " "
".constructor(+[](::com::sun::star::uno::Reference<::com::sun::star::uno::"
"XInterface> const & the_object) { return ::com::sun::star::uno::Reference<"
<< cppName(ifc) << cppName(ifc)
<< ">::is)\n" << ">(the_object, ::com::sun::star::uno::UNO_QUERY); })\n"
" .function(\"get\", &::com::sun::star::uno::Reference<" " .constructor(+[](::com::sun::star::uno::Any const & the_object, "
"[[maybe_unused]] ::unoembindhelpers::uno_Reference) { return "
"::com::sun::star::uno::Reference<"
<< cppName(ifc) << cppName(ifc)
<< ">::get, ::emscripten::allow_raw_pointers())\n" << ">(the_object, ::com::sun::star::uno::UNO_QUERY); })\n"
" .function(\"set\", " " .function(\"$is\", +[](::com::sun::star::uno::Reference<"
"::emscripten::select_overload<bool(::com::sun::star::uno::Any const " << cppName(ifc)
"&, " << "> const & the_self) { return the_self.is(); })\n"
"com::sun::star::uno::UnoReference_Query)>(&::com::sun::star::uno::" " .function(\"$query\", +[](::com::sun::star::uno::Reference<"
"Reference<" << cppName(ifc)
<< cppName(ifc) << ">::set))\n"; << "> const & the_self) { return "
"::com::sun::star::uno::Reference<::com::sun::star::uno::XInterface>(the_"
"self); })\n";
dumpAttributes(cppOut, ifc, ifcEnt); dumpAttributes(cppOut, ifc, ifcEnt);
dumpMethods(cppOut, mgr, ifc, ifcEnt, true); dumpMethods(cppOut, mgr, ifc, ifcEnt);
cppOut << " ;\n" cppOut << " ;\n"
"}\n"; "}\n";
++n; ++n;

View File

@ -13,6 +13,7 @@
#include <sal/log.hxx> #include <sal/log.hxx>
#include <sfx2/viewsh.hxx> #include <sfx2/viewsh.hxx>
#include <static/unoembindhelpers/PrimaryBindings.hxx>
using namespace emscripten; using namespace emscripten;
using namespace css::uno; using namespace css::uno;
@ -34,8 +35,8 @@ Reference<css::frame::XModel> getCurrentModelFromViewSh()
EMSCRIPTEN_BINDINGS(PrimaryBindings) EMSCRIPTEN_BINDINGS(PrimaryBindings)
{ {
// Reference bits // Reference bits
class_<BaseReference>("BaseReference"); enum_<unoembindhelpers::uno_Reference>("uno_Reference")
enum_<UnoReference_Query>("UnoReference_Query").value("UNO_QUERY", UNO_QUERY); .value("FromAny", unoembindhelpers::uno_Reference::FromAny);
class_<OUString>("OUString") class_<OUString>("OUString")
.constructor(+[](const std::u16string& rString) -> OUString { return OUString(rString); }, .constructor(+[](const std::u16string& rString) -> OUString { return OUString(rString); },