static/source/unoembindhelpers/PrimaryBindings.cxx | 43 +++++++++++++++++++++ udkapi/org/libreoffice/embindtest/XTest.idl | 4 + unotest/source/embindtest/embindtest.cxx | 24 +++++++++++ unotest/source/embindtest/embindtest.js | 16 +++++++ 4 files changed, 87 insertions(+)
New commits: commit 41feb036b44ffefca898f44ed95a2129d779da59 Author: Stephan Bergmann <stephan.bergm...@allotropia.de> AuthorDate: Thu Feb 29 08:54:08 2024 +0100 Commit: Stephan Bergmann <stephan.bergm...@allotropia.de> CommitDate: Thu Feb 29 16:19:19 2024 +0100 Some minimal Embind support for UNO type ...which should be rare enough in practical use that it should be sufficient to only have toString-functionality for instances mapped from C++ to JS, but no constructor for new instances on the JS side. (The natural choice for the latter would be a mapping of the C++ > inline Type( TypeClass eTypeClass, const ::rtl::OUString & rTypeName ); constructor, but which requires a mapping for the css::uno::TypeClass UNOIDL enum, which is only provided "later" through CustomTarget_static/unoembind, so would at least conceptually be a bit dirty.) This Embind mapping treats css::uno::Type as a smart pointer for the underlying typelib_TypeDescriptionReference, to benefit from the fallback garbage collection (in more recent Emscripten versions, at least) for smart pointers, obviating the need to call .delete() on each instance mapped to JS. Change-Id: Ic113967c264c28641dfd1fe159012c85519f4a9b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164140 Tested-by: Jenkins Reviewed-by: Stephan Bergmann <stephan.bergm...@allotropia.de> diff --git a/static/source/unoembindhelpers/PrimaryBindings.cxx b/static/source/unoembindhelpers/PrimaryBindings.cxx index 186e3ee88057..50048a97ada6 100644 --- a/static/source/unoembindhelpers/PrimaryBindings.cxx +++ b/static/source/unoembindhelpers/PrimaryBindings.cxx @@ -12,17 +12,41 @@ #include <emscripten.h> #include <emscripten/bind.h> +#include <com/sun/star/uno/RuntimeException.hpp> +#include <com/sun/star/uno/Type.hxx> #include <comphelper/processfactory.hxx> +#include <rtl/string.hxx> +#include <rtl/textcvt.h> +#include <rtl/textenc.h> +#include <rtl/ustring.hxx> #include <sal/log.hxx> #include <sfx2/viewsh.hxx> #include <static/unoembindhelpers/PrimaryBindings.hxx> +#include <typelib/typedescription.h> #include <cstdint> +#include <string> #include <typeinfo> using namespace emscripten; using namespace css::uno; +template <> struct emscripten::smart_ptr_trait<css::uno::Type> +{ + using PointerType = css::uno::Type; + using element_type = typelib_TypeDescriptionReference; + static typelib_TypeDescriptionReference* get(css::uno::Type const& ptr) + { + return ptr.getTypeLibType(); + } + static sharing_policy get_sharing_policy() { return sharing_policy::INTRUSIVE; } + static css::uno::Type* share(typelib_TypeDescriptionReference* v) + { + return new css::uno::Type(v); + } + static css::uno::Type* construct_null() { return new css::uno::Type(); } +}; + EM_JS(void, jsRegisterChar, (std::type_info const* raw), // clang-format off { @@ -110,6 +134,18 @@ EM_JS(void, jsRegisterString, (std::type_info const* raw), namespace { +OString toUtf8(OUString const& string) +{ + OString s; + if (!string.convertToString(&s, RTL_TEXTENCODING_UTF8, + RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR + | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)) + { + throw css::uno::RuntimeException("cannot convert OUString to UTF-8"); + } + return s; +} + template <typename T> void registerInOutParam(char const* name) { class_<unoembindhelpers::UnoInOutParam<T>>(name).constructor().constructor<T>().property( @@ -135,6 +171,13 @@ EMSCRIPTEN_BINDINGS(PrimaryBindings) enum_<unoembindhelpers::uno_Sequence>("uno_Sequence") .value("FromSize", unoembindhelpers::uno_Sequence::FromSize); + emscripten::class_<typelib_TypeDescriptionReference>("uno_Type") + .smart_ptr<css::uno::Type>("uno_Type$") + .function("toString", +[](css::uno::Type const& self) { + auto const name = toUtf8(self.getTypeName()); + return std::string(name.getStr(), name.getLength()); + }); + // Any class_<Any>("Any").constructor(+[](const val& rObject, const TypeClass& rUnoType) -> Any { switch (rUnoType) diff --git a/udkapi/org/libreoffice/embindtest/XTest.idl b/udkapi/org/libreoffice/embindtest/XTest.idl index f64a3857e863..2ddfb41f2ead 100644 --- a/udkapi/org/libreoffice/embindtest/XTest.idl +++ b/udkapi/org/libreoffice/embindtest/XTest.idl @@ -34,6 +34,8 @@ interface XTest { boolean isChar([in] char value); string getString(); boolean isString([in] string value); + type getType(); + boolean isType([in] type value); Enum getEnum(); boolean isEnum([in] Enum value); Struct getStruct(); @@ -62,6 +64,8 @@ interface XTest { boolean isSequenceChar([in] sequence<char> value); sequence<string> getSequenceString(); boolean isSequenceString([in] sequence<string> value); + sequence<type> getSequenceType(); + boolean isSequenceType([in] sequence<type> value); sequence<sequence<string> > getSequenceSequenceString(); boolean isSequenceSequenceString([in] sequence<sequence<string> > value); sequence<Enum> getSequenceEnum(); diff --git a/unotest/source/embindtest/embindtest.cxx b/unotest/source/embindtest/embindtest.cxx index 2a9cdfc4de3a..8b131cd9f376 100644 --- a/unotest/source/embindtest/embindtest.cxx +++ b/unotest/source/embindtest/embindtest.cxx @@ -10,6 +10,8 @@ #include <sal/config.h> #include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/uno/Type.hxx> +#include <cppu/unotype.hxx> #include <cppuhelper/implbase.hxx> #include <cppuhelper/weak.hxx> #include <org/libreoffice/embindtest/Struct.hpp> @@ -76,6 +78,13 @@ public: sal_Bool SAL_CALL isString(OUString const& value) override { return value == u"hä"; } + css::uno::Type SAL_CALL getType() override { return cppu::UnoType<sal_Int32>::get(); } + + sal_Bool SAL_CALL isType(css::uno::Type const& value) override + { + return value == cppu::UnoType<sal_Int32>::get(); + } + org::libreoffice::embindtest::Enum SAL_CALL getEnum() override { return org::libreoffice::embindtest::Enum_E_2; @@ -213,6 +222,21 @@ public: return value == css::uno::Sequence<OUString>{ u"foo"_ustr, u"barr"_ustr, u"bazzz"_ustr }; } + css::uno::Sequence<css::uno::Type> SAL_CALL getSequenceType() override + { + return { cppu::UnoType<sal_Int32>::get(), cppu::UnoType<void>::get(), + cppu::UnoType<css::uno::Sequence<org::libreoffice::embindtest::Enum>>::get() }; + } + + sal_Bool SAL_CALL isSequenceType(css::uno::Sequence<css::uno::Type> const& value) override + { + return value + == css::uno::Sequence<css::uno::Type>{ + cppu::UnoType<sal_Int32>::get(), cppu::UnoType<void>::get(), + cppu::UnoType<css::uno::Sequence<org::libreoffice::embindtest::Enum>>::get() + }; + } + css::uno::Sequence<css::uno::Sequence<OUString>> SAL_CALL getSequenceSequenceString() override { return { {}, { u"foo"_ustr, u"barr"_ustr }, { u"baz"_ustr } }; diff --git a/unotest/source/embindtest/embindtest.js b/unotest/source/embindtest/embindtest.js index 1978c9cc4ec7..422c1c1a421f 100644 --- a/unotest/source/embindtest/embindtest.js +++ b/unotest/source/embindtest/embindtest.js @@ -84,6 +84,12 @@ Module.addOnPostRun(function() { console.assert(v === 'hä'); console.assert(test.isString(v)); } + { + let v = test.getType(); + console.log(v); + console.assert(v.toString() === 'long'); + console.assert(test.isType(v)); + } { let v = test.getEnum(); console.log(v); @@ -218,6 +224,16 @@ Module.addOnPostRun(function() { console.assert(test.isSequenceString(v)); v.delete(); } + { + let v = test.getSequenceType(); + console.log(v); + console.assert(v.size() === 3); + console.assert(v.get(0).toString() === 'long'); + console.assert(v.get(1).toString() === 'void'); + console.assert(v.get(2).toString() === '[]org.libreoffice.embindtest.Enum'); + console.assert(test.isSequenceType(v)); + v.delete(); + } { let v = test.getSequenceSequenceString(); console.log(v);