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);
let css = Module.unoembind_uno.com.sun.star;
xModel = Module.getCurrentModelFromViewSh();
xTextDocument = new css.text.XTextDocument(xModel, Module.UnoReference_Query.UNO_QUERY);
xTextDocument = new css.text.XTextDocument(xModel.$query());
xText = xTextDocument.getText();
xSimpleText = new css.text.XSimpleText(xText, Module.UnoReference_Query.UNO_QUERY);
xSimpleText = new css.text.XSimpleText(xText.$query());
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!"));
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);
let css = Module.unoembind_uno.com.sun.star;
xModel = Module.getCurrentModelFromViewSh();
xTextDocument = new css.text.XTextDocument(xModel, Module.UnoReference_Query.UNO_QUERY);
xText = xTextDocument.getText();
xEnumAccess = new css.container.XEnumerationAccess(xText, Module.UnoReference_Query.UNO_QUERY);
init_unoembind_uno(Module);
xEnumAccess = new css.container.XEnumerationAccess(xText.$query());
xParaEnumeration = xEnumAccess.createEnumeration();
while (xParaEnumeration.hasMoreElements()) {
xParagraph = new css.text.XTextRange();
xParagraph.set(xParaEnumeration.nextElement(), Module.UnoReference_Query.UNO_QUERY);
if (xParagraph.is()) {
xParaProps = new css.beans.XPropertySet(xParagraph, Module.UnoReference_Query.UNO_QUERY);
xParagraph = new css.text.XTextRange(xParaEnumeration.nextElement(), Module.uno_Reference.FromAny);
if (xParagraph.$is()) {
xParaProps = new css.beans.XPropertySet(xParagraph.$query());
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,
OUString const& interfaceName, unoidl::InterfaceTypeEntity::Method const& method,
bool forReference)
OUString const& interfaceName, unoidl::InterfaceTypeEntity::Method const& method)
{
out << " .function(\"" << method.name << "\", +[](";
if (forReference)
{
out << "::com::sun::star::uno::Reference<";
}
out << cppName(interfaceName);
if (forReference)
{
out << ">";
}
out << " .function(\"" << method.name << "\", +[](" << cppName(interfaceName);
out << " * the_self";
if (!method.parameters.empty())
{
out << ", ";
}
dumpParameters(out, manager, method, true);
out << ") { return the_self->";
if (forReference)
{
out << "get()->";
}
out << method.name << "(";
out << ") { return the_self->" << method.name << "(";
dumpParameters(out, manager, method, false);
out << "); }, ::emscripten::allow_raw_pointers())\n";
}
void dumpMethods(std::ostream& out, rtl::Reference<TypeManager> const& manager,
OUString const& name, rtl::Reference<unoidl::InterfaceTypeEntity> const& entity,
bool forReference)
OUString const& name, rtl::Reference<unoidl::InterfaceTypeEntity> const& entity)
{
for (auto const& meth : entity->getDirectMethods())
{
if (forReference)
{
dumpWrapper(out, manager, name, meth, true);
}
else if (std::any_of(
meth.parameters.begin(), meth.parameters.end(), [](auto const& parameter) {
if (std::any_of(meth.parameters.begin(), meth.parameters.end(), [](auto const& parameter) {
return parameter.direction
!= unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN;
}))
{
dumpWrapper(out, manager, name, meth, false);
dumpWrapper(out, manager, name, meth);
}
else
{
@ -455,7 +434,7 @@ void writeJsMap(std::ostream& out, Module const& module, std::string const& pref
{
out << ",\n";
}
out << prefix << "'" << ifc.copy(ifc.lastIndexOf('.') + 1) << "': instance.uno_Reference_"
out << prefix << "'" << ifc.copy(ifc.lastIndexOf('.') + 1) << "': instance.uno_Type_"
<< jsName(ifc);
comma = true;
}
@ -518,7 +497,8 @@ SAL_IMPLEMENT_MAIN()
}
cppOut << "#include <emscripten/bind.h>\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)
{
cppOut << "#include <" << ifc.replace('.', '/') << ".hpp>\n";
@ -544,33 +524,31 @@ SAL_IMPLEMENT_MAIN()
cppOut << "static void __attribute__((noinline)) register" << n
<< "() {\n"
" ::emscripten::class_<"
<< cppName(ifc) << ">(\"uno_Type_" << 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>>(\"uno_Reference_"
<< jsName(ifc)
<< cppName(ifc) << ">(\"uno_Type_" << jsName(ifc)
<< "\")\n"
" .constructor<>()\n"
" .constructor<::com::sun::star::uno::BaseReference, "
"::com::sun::star::uno::UnoReference_Query>()\n"
" .function(\"is\", &::com::sun::star::uno::Reference<"
" .smart_ptr<::com::sun::star::uno::Reference<"
<< cppName(ifc) << ">>(\"uno_Reference_" << jsName(ifc)
<< "\")\n"
" "
".constructor(+[](::com::sun::star::uno::Reference<::com::sun::star::uno::"
"XInterface> const & the_object) { return ::com::sun::star::uno::Reference<"
<< cppName(ifc)
<< ">::is)\n"
" .function(\"get\", &::com::sun::star::uno::Reference<"
<< ">(the_object, ::com::sun::star::uno::UNO_QUERY); })\n"
" .constructor(+[](::com::sun::star::uno::Any const & the_object, "
"[[maybe_unused]] ::unoembindhelpers::uno_Reference) { return "
"::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";
<< ">(the_object, ::com::sun::star::uno::UNO_QUERY); })\n"
" .function(\"$is\", +[](::com::sun::star::uno::Reference<"
<< cppName(ifc)
<< "> const & the_self) { return the_self.is(); })\n"
" .function(\"$query\", +[](::com::sun::star::uno::Reference<"
<< cppName(ifc)
<< "> const & the_self) { return "
"::com::sun::star::uno::Reference<::com::sun::star::uno::XInterface>(the_"
"self); })\n";
dumpAttributes(cppOut, ifc, ifcEnt);
dumpMethods(cppOut, mgr, ifc, ifcEnt, true);
dumpMethods(cppOut, mgr, ifc, ifcEnt);
cppOut << " ;\n"
"}\n";
++n;

View File

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