diff --git a/bridges/CustomTarget_gcc3_wasm.mk b/bridges/CustomTarget_gcc3_wasm.mk index 7452fc477e4f..0393b1b8193b 100644 --- a/bridges/CustomTarget_gcc3_wasm.mk +++ b/bridges/CustomTarget_gcc3_wasm.mk @@ -10,19 +10,19 @@ $(eval $(call gb_CustomTarget_CustomTarget,bridges/gcc3_wasm)) $(eval $(call gb_CustomTarget_register_targets,bridges/gcc3_wasm, \ - callvirtualfunction-wrapper.cxx \ - callvirtualfunction-impls.s \ + generated-cxx.cxx \ + generated-asm.s \ exports \ )) -$(gb_CustomTarget_workdir)/bridges/gcc3_wasm/callvirtualfunction-impls.s \ -$(gb_CustomTarget_workdir)/bridges/gcc3_wasm/callvirtualfunction-wrapper.cxx \ +$(gb_CustomTarget_workdir)/bridges/gcc3_wasm/generated-asm.s \ +$(gb_CustomTarget_workdir)/bridges/gcc3_wasm/generated-cxx.cxx \ $(gb_CustomTarget_workdir)/bridges/gcc3_wasm/exports: \ $(call gb_Executable_get_target_for_build,wasmcallgen) $(call gb_UnoApi_get_target,udkapi) \ $(call gb_UnoApi_get_target,offapi) $(call gb_Executable_get_command,wasmcallgen) \ - $(gb_CustomTarget_workdir)/bridges/gcc3_wasm/callvirtualfunction-wrapper.cxx \ - $(gb_CustomTarget_workdir)/bridges/gcc3_wasm/callvirtualfunction-impls.s \ + $(gb_CustomTarget_workdir)/bridges/gcc3_wasm/generated-cxx.cxx \ + $(gb_CustomTarget_workdir)/bridges/gcc3_wasm/generated-asm.s \ $(gb_CustomTarget_workdir)/bridges/gcc3_wasm/exports \ +$(call gb_UnoApi_get_target,udkapi) +$(call gb_UnoApi_get_target,offapi) diff --git a/bridges/Library_cpp_uno.mk b/bridges/Library_cpp_uno.mk index 5ee781e7aa8c..94f17f0149b0 100644 --- a/bridges/Library_cpp_uno.mk +++ b/bridges/Library_cpp_uno.mk @@ -85,10 +85,10 @@ else ifeq ($(OS),EMSCRIPTEN) bridges_SELECTED_BRIDGE := gcc3_wasm bridge_exception_objects := abi cpp2uno uno2cpp $(eval $(call gb_Library_add_generated_asmobjects,$(CPPU_ENV)_uno, \ - CustomTarget/bridges/gcc3_wasm/callvirtualfunction-impls \ + CustomTarget/bridges/gcc3_wasm/generated-asm \ )) $(eval $(call gb_Library_add_generated_exception_objects,$(CPPU_ENV)_uno, \ - CustomTarget/bridges/gcc3_wasm/callvirtualfunction-wrapper \ + CustomTarget/bridges/gcc3_wasm/generated-cxx \ )) $(eval $(call gb_Library_use_static_libraries,$(CPPU_ENV)_uno, \ emscriptencxxabi \ diff --git a/bridges/inc/wasm/callvirtualfunction.hxx b/bridges/inc/wasm/generated.hxx similarity index 72% rename from bridges/inc/wasm/callvirtualfunction.hxx rename to bridges/inc/wasm/generated.hxx index 23b446cd45b3..b37fc589c1bf 100644 --- a/bridges/inc/wasm/callvirtualfunction.hxx +++ b/bridges/inc/wasm/generated.hxx @@ -12,10 +12,16 @@ #include #include +#include #include void callVirtualFunction(std::string_view signature, sal_uInt32 target, sal_uInt64 const* arguments, void* returnValue); +sal_uInt64 vtableCall(sal_Int32 functionIndex, sal_Int32 vtableOffset, unsigned thisPtr, + std::vector const& arguments, unsigned indirectRet); + +void const* getVtableSlotFunction(std::string_view signature); + /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/bridges/source/cpp_uno/gcc3_wasm/cpp2uno.cxx b/bridges/source/cpp_uno/gcc3_wasm/cpp2uno.cxx index 921e2f23b551..000a364e0c40 100644 --- a/bridges/source/cpp_uno/gcc3_wasm/cpp2uno.cxx +++ b/bridges/source/cpp_uno/gcc3_wasm/cpp2uno.cxx @@ -9,6 +9,7 @@ #include +#include #include #include @@ -24,6 +25,7 @@ #include #include #include +#include #include "abi.hxx" @@ -176,19 +178,21 @@ void raiseException(uno_Any* any, uno_Mapping* mapping) __cxxabiv1::__cxa_throw(exc, rtti, deleteException); } -void call(bridges::cpp_uno::shared::CppInterfaceProxy* proxy, - css::uno::TypeDescription const& description, - typelib_TypeDescriptionReference* returnType, sal_Int32 count, - typelib_MethodParameter* parameters, std::vector arguments, - unsigned /*indirectRect*/) +sal_uInt64 call(bridges::cpp_uno::shared::CppInterfaceProxy* proxy, + css::uno::TypeDescription const& description, + typelib_TypeDescriptionReference* returnType, sal_Int32 count, + typelib_MethodParameter* parameters, std::vector arguments, + unsigned indirectRet) { typelib_TypeDescription* rtd = nullptr; if (returnType != nullptr) { TYPELIB_DANGER_GET(&rtd, returnType); } - void* retin = nullptr; - + auto const retConv = rtd != nullptr && bridges::cpp_uno::shared::relatesToInterfaceType(rtd); + void* retin = reinterpret_cast(indirectRet) != nullptr && !retConv + ? reinterpret_cast(indirectRet) + : rtd == nullptr ? nullptr : alloca(rtd->nSize); void** args = static_cast(alloca(count * sizeof(void*))); void** cppArgs = static_cast(alloca(count * sizeof(void*))); typelib_TypeDescription** argtds @@ -198,7 +202,8 @@ void call(bridges::cpp_uno::shared::CppInterfaceProxy* proxy, { if (!parameters[i].bOut && bridges::cpp_uno::shared::isSimpleType(parameters[i].pTypeRef)) { - assert(false); + args[i] = arguments.data() + i; + argtds[i] = nullptr; } else { @@ -246,11 +251,54 @@ void call(bridges::cpp_uno::shared::CppInterfaceProxy* proxy, } raiseException(&exc, proxy->getBridge()->getUno2Cpp()); } - assert(false); + for (sal_Int32 i = 0; i != count; ++i) + { + if (argtds[i] != nullptr) + { + if (parameters[i].bOut) + { + uno_destructData(cppArgs[i], argtds[i], + reinterpret_cast(css::uno::cpp_release)); + uno_copyAndConvertData(cppArgs[i], args[i], argtds[i], + proxy->getBridge()->getUno2Cpp()); + } + uno_destructData(args[i], argtds[i], nullptr); + TYPELIB_DANGER_RELEASE(argtds[i]); + } + } + sal_uInt64 retVal = {}; + if (retConv) + { + uno_copyAndConvertData(reinterpret_cast(indirectRet), retin, rtd, + proxy->getBridge()->getUno2Cpp()); + uno_destructData(retin, rtd, nullptr); + } + else if (rtd != nullptr) + { + // Make sure to sign-extend the return value for small signed integer types: + switch (rtd->eTypeClass) + { + case typelib_TypeClass_BYTE: + retVal = static_cast(*static_cast(retin)); + break; + case typelib_TypeClass_SHORT: + retVal = static_cast(*static_cast(retin)); + break; + default: + std::memcpy(&retVal, retin, rtd->nSize); + break; + } + } + if (rtd != nullptr) + { + TYPELIB_DANGER_RELEASE(rtd); + } + return retVal; +} } -void vtableCall(sal_Int32 functionIndex, sal_Int32 vtableOffset, unsigned thisPtr, - std::vector const& arguments, unsigned indirectRet) +sal_uInt64 vtableCall(sal_Int32 functionIndex, sal_Int32 vtableOffset, unsigned thisPtr, + std::vector const& arguments, unsigned indirectRet) { bridges::cpp_uno::shared::CppInterfaceProxy* proxy = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy( @@ -265,10 +313,10 @@ void vtableCall(sal_Int32 functionIndex, sal_Int32 vtableOffset, unsigned thisPt if (type->pMapMemberIndexToFunctionIndex[pos] == functionIndex) { // Getter: - call(proxy, desc, - reinterpret_cast(desc.get()) - ->pAttributeTypeRef, - 0, nullptr, arguments, indirectRet); + return call(proxy, desc, + reinterpret_cast(desc.get()) + ->pAttributeTypeRef, + 0, nullptr, arguments, indirectRet); } else { @@ -278,7 +326,7 @@ void vtableCall(sal_Int32 functionIndex, sal_Int32 vtableOffset, unsigned thisPt reinterpret_cast(desc.get()) ->pAttributeTypeRef, true, false }; - call(proxy, desc, nullptr, 1, ¶m, arguments, indirectRet); + return call(proxy, desc, nullptr, 1, ¶m, arguments, indirectRet); } break; case typelib_TypeClass_INTERFACE_METHOD: @@ -286,10 +334,10 @@ void vtableCall(sal_Int32 functionIndex, sal_Int32 vtableOffset, unsigned thisPt { case 1: proxy->acquireProxy(); - break; + return {}; case 2: proxy->releaseProxy(); - break; + return {}; case 0: { typelib_TypeDescription* td = nullptr; @@ -309,78 +357,135 @@ void vtableCall(sal_Int32 functionIndex, sal_Int32 vtableOffset, unsigned thisPt reinterpret_cast(css::uno::cpp_acquire)); ifc->release(); TYPELIB_DANGER_RELEASE(td); - break; + return {}; } TYPELIB_DANGER_RELEASE(td); } } [[fallthrough]]; default: - call(proxy, desc, - reinterpret_cast(desc.get()) - ->pReturnTypeRef, - reinterpret_cast(desc.get()) - ->nParams, - reinterpret_cast(desc.get()) - ->pParams, - arguments, indirectRet); - break; + return call( + proxy, desc, + reinterpret_cast(desc.get()) + ->pReturnTypeRef, + reinterpret_cast(desc.get()) + ->nParams, + reinterpret_cast(desc.get()) + ->pParams, + arguments, indirectRet); } - break; default: O3TL_UNREACHABLE; } } -extern "C" void vtableSlotFunction_0_0Ii(unsigned indirectRet, unsigned thisPtr, unsigned arg1) +namespace { - vtableCall(0, 0, thisPtr, { sal_uInt64(arg1) }, indirectRet); +void appendSignatureOffsets(OStringBuffer& buffer, sal_Int32 functionOffset, sal_Int32 vtableOffset) +{ + buffer.append(OString::number(functionOffset) + "_" + OString::number(vtableOffset)); } -extern "C" void vtableSlotFunction_1_0v(unsigned thisPtr) +void appendSignatureReturnType(OStringBuffer& buffer, typelib_TypeDescriptionReference* type) { - vtableCall(1, 0, thisPtr, {}, reinterpret_cast(nullptr)); + switch (type->eTypeClass) + { + case typelib_TypeClass_VOID: + buffer.append('v'); + break; + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + case typelib_TypeClass_LONG: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_CHAR: + case typelib_TypeClass_ENUM: + buffer.append('i'); + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + buffer.append('j'); + break; + case typelib_TypeClass_FLOAT: + buffer.append('f'); + break; + case typelib_TypeClass_DOUBLE: + buffer.append('d'); + break; + case typelib_TypeClass_STRING: + case typelib_TypeClass_TYPE: + case typelib_TypeClass_ANY: + case typelib_TypeClass_SEQUENCE: + case typelib_TypeClass_INTERFACE: + buffer.append('I'); + break; + case typelib_TypeClass_STRUCT: + { + css::uno::TypeDescription td(type); + switch (abi_wasm::getKind( + reinterpret_cast(td.get()))) + { + case abi_wasm::StructKind::Empty: + break; + case abi_wasm::StructKind::I32: + buffer.append('i'); + break; + case abi_wasm::StructKind::I64: + buffer.append('j'); + break; + case abi_wasm::StructKind::F32: + buffer.append('f'); + break; + case abi_wasm::StructKind::F64: + buffer.append('d'); + break; + case abi_wasm::StructKind::General: + buffer.append('I'); + break; + } + break; + } + default: + O3TL_UNREACHABLE; + } } -extern "C" void vtableSlotFunction_2_0v(unsigned thisPtr) +void appendSignatureParameter(OStringBuffer& buffer, bool out, + typelib_TypeDescriptionReference const* type) { - vtableCall(2, 0, thisPtr, {}, reinterpret_cast(nullptr)); -} - -extern "C" void vtableSlotFunction_3_0vi(unsigned thisPtr, unsigned arg1) -{ - vtableCall(3, 0, thisPtr, { arg1 }, reinterpret_cast(nullptr)); -} - -extern "C" void vtableSlotFunction_4_0v(unsigned thisPtr) -{ - vtableCall(4, 0, thisPtr, {}, reinterpret_cast(nullptr)); -} - -void const* getVtableSlotFunction(std::string_view signature) -{ - if (signature == "0_0Ii") + if (!out && bridges::cpp_uno::shared::isSimpleType(type)) { - return reinterpret_cast(vtableSlotFunction_0_0Ii); + switch (type->eTypeClass) + { + case typelib_TypeClass_BOOLEAN: + case typelib_TypeClass_BYTE: + case typelib_TypeClass_SHORT: + case typelib_TypeClass_UNSIGNED_SHORT: + case typelib_TypeClass_LONG: + case typelib_TypeClass_ENUM: + case typelib_TypeClass_UNSIGNED_LONG: + case typelib_TypeClass_CHAR: + buffer.append('i'); + break; + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + buffer.append('j'); + break; + case typelib_TypeClass_FLOAT: + buffer.append('f'); + break; + case typelib_TypeClass_DOUBLE: + buffer.append('d'); + break; + default: + O3TL_UNREACHABLE; + } } - if (signature == "1_0v") + else { - return reinterpret_cast(vtableSlotFunction_1_0v); + buffer.append('i'); } - if (signature == "2_0v") - { - return reinterpret_cast(vtableSlotFunction_2_0v); - } - if (signature == "3_0vi") - { - return reinterpret_cast(vtableSlotFunction_3_0vi); - } - if (signature == "4_0v") - { - return reinterpret_cast(vtableSlotFunction_4_0v); - } - throw css::uno::RuntimeException("Wasm bridge cannot fill virtual function slot with signature " - + OUString::fromUtf8(signature)); } } @@ -396,132 +501,37 @@ unsigned char* VtableFactory::addLocalFunctions(Slot** slots, unsigned char* cod switch (type->ppMembers[i]->eTypeClass) { case typelib_TypeClass_INTERFACE_ATTRIBUTE: - (s++)->fn = nullptr; //TODO + { + auto const atd = reinterpret_cast( + css::uno::TypeDescription(type->ppMembers[i]).get()); + OStringBuffer sigGetter; + appendSignatureOffsets(sigGetter, functionOffset, vtableOffset); + appendSignatureReturnType(sigGetter, atd->pAttributeTypeRef); + (s++)->fn = getVtableSlotFunction(sigGetter); ++functionOffset; if (!reinterpret_cast( css::uno::TypeDescription(type->ppMembers[i]).get()) ->bReadOnly) { - (s++)->fn = nullptr; //TODO + OStringBuffer sigSetter; + appendSignatureOffsets(sigSetter, functionOffset, vtableOffset); + sigSetter.append('v'); + appendSignatureParameter(sigSetter, false, atd->pAttributeTypeRef); + (s++)->fn = getVtableSlotFunction(sigSetter); ++functionOffset; } break; + } case typelib_TypeClass_INTERFACE_METHOD: { - OStringBuffer sig; - sig.append(OString::number(functionOffset) + "_" + OString::number(vtableOffset)); auto const mtd = reinterpret_cast( css::uno::TypeDescription(type->ppMembers[i]).get()); - switch (mtd->pReturnTypeRef->eTypeClass) - { - case typelib_TypeClass_VOID: - sig.append('v'); - break; - case typelib_TypeClass_BOOLEAN: - case typelib_TypeClass_BYTE: - case typelib_TypeClass_SHORT: - case typelib_TypeClass_UNSIGNED_SHORT: - case typelib_TypeClass_LONG: - case typelib_TypeClass_UNSIGNED_LONG: - case typelib_TypeClass_CHAR: - case typelib_TypeClass_ENUM: - sig.append('i'); - break; - case typelib_TypeClass_HYPER: - case typelib_TypeClass_UNSIGNED_HYPER: - sig.append('j'); - break; - case typelib_TypeClass_FLOAT: - sig.append('f'); - break; - case typelib_TypeClass_DOUBLE: - sig.append('d'); - break; - case typelib_TypeClass_STRING: - case typelib_TypeClass_TYPE: - case typelib_TypeClass_ANY: - case typelib_TypeClass_SEQUENCE: - case typelib_TypeClass_INTERFACE: - sig.append('I'); - break; - case typelib_TypeClass_STRUCT: - { - css::uno::TypeDescription rtd(mtd->pReturnTypeRef); - switch (abi_wasm::getKind( - reinterpret_cast(rtd.get()))) - { - case abi_wasm::StructKind::Empty: - break; - case abi_wasm::StructKind::I32: - sig.append('i'); - break; - case abi_wasm::StructKind::I64: - sig.append('j'); - break; - case abi_wasm::StructKind::F32: - sig.append('f'); - break; - case abi_wasm::StructKind::F64: - sig.append('d'); - break; - case abi_wasm::StructKind::General: - sig.append('I'); - break; - } - break; - } - default: - O3TL_UNREACHABLE; - } + OStringBuffer sig; + appendSignatureOffsets(sig, functionOffset, vtableOffset); + appendSignatureReturnType(sig, mtd->pReturnTypeRef); for (sal_Int32 j = 0; j != mtd->nParams; ++j) { - if (!mtd->pParams[j].bOut - && bridges::cpp_uno::shared::isSimpleType(mtd->pParams[j].pTypeRef)) - { - switch (mtd->pParams[j].pTypeRef->eTypeClass) - { - case typelib_TypeClass_BOOLEAN: - sig.append('i'); - break; - case typelib_TypeClass_BYTE: - sig.append('i'); - break; - case typelib_TypeClass_SHORT: - sig.append('i'); - break; - case typelib_TypeClass_UNSIGNED_SHORT: - sig.append('i'); - break; - case typelib_TypeClass_LONG: - case typelib_TypeClass_ENUM: - sig.append('i'); - break; - case typelib_TypeClass_UNSIGNED_LONG: - sig.append('i'); - break; - case typelib_TypeClass_HYPER: - sig.append('j'); - break; - case typelib_TypeClass_UNSIGNED_HYPER: - sig.append('j'); - break; - case typelib_TypeClass_FLOAT: - sig.append('f'); - break; - case typelib_TypeClass_DOUBLE: - sig.append('d'); - break; - case typelib_TypeClass_CHAR: - sig.append('i'); - break; - default: - O3TL_UNREACHABLE; - } - } - else - { - sig.append('i'); - } + appendSignatureParameter(sig, mtd->pParams[j].bOut, mtd->pParams[j].pTypeRef); } (s++)->fn = getVtableSlotFunction(sig); ++functionOffset; diff --git a/bridges/source/cpp_uno/gcc3_wasm/uno2cpp.cxx b/bridges/source/cpp_uno/gcc3_wasm/uno2cpp.cxx index f3467c497460..f3b257dc1d9b 100644 --- a/bridges/source/cpp_uno/gcc3_wasm/uno2cpp.cxx +++ b/bridges/source/cpp_uno/gcc3_wasm/uno2cpp.cxx @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include "abi.hxx" diff --git a/offapi/UnoApi_offapi.mk b/offapi/UnoApi_offapi.mk index fe01fc172776..096a55e69d38 100644 --- a/offapi/UnoApi_offapi.mk +++ b/offapi/UnoApi_offapi.mk @@ -4449,6 +4449,7 @@ $(eval $(call gb_UnoApi_add_idlfiles,offapi,org/libreoffice/embindtest, \ XTest \ )) $(eval $(call gb_UnoApi_add_idlfiles_nohdl,offapi,org/libreoffice/embindtest, \ + BridgeTest \ Test \ )) endif diff --git a/offapi/org/libreoffice/embindtest/BridgeTest.idl b/offapi/org/libreoffice/embindtest/BridgeTest.idl new file mode 100644 index 000000000000..ed34bd56ea4c --- /dev/null +++ b/offapi/org/libreoffice/embindtest/BridgeTest.idl @@ -0,0 +1,16 @@ +/* -*- 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/. + */ + +module org { module libreoffice { module embindtest { + +singleton BridgeTest: com::sun::star::task::XJob; + +}; }; }; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/static/source/wasmcallgen/wasmcallgen.cxx b/static/source/wasmcallgen/wasmcallgen.cxx index 2c61a48c6b25..0c7b93c76f39 100644 --- a/static/source/wasmcallgen/wasmcallgen.cxx +++ b/static/source/wasmcallgen/wasmcallgen.cxx @@ -25,9 +25,12 @@ #include #include #include +#include +#include #include #include #include +#include #include #include #include @@ -49,9 +52,9 @@ namespace " wasmcallgen \n\n" "where each 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. For all primary registries, Wasm UNO bridge callvirtualfunction\n" - "code is written to /, and to-be-exported exception RTTI\n" - "symbols are written to .\n"; + ".idl file tree. For all primary registries, Wasm UNO bridge code is written to\n" + "/, and to-be-exported exception RTTI symbols are written\n" + "to .\n"; std::exit(EXIT_FAILURE); } @@ -245,14 +248,13 @@ StructKind getKind(rtl::Reference const& manager, std::u16string_vi } } -OString computeSignature(rtl::Reference const& manager, - unoidl::InterfaceTypeEntity::Method const& method) +void appendCallSignatureReturnType(OStringBuffer& buffer, + rtl::Reference const& manager, OUString const& type) { - OStringBuffer buf; - switch (manager->getSort(resolveAllTypedefs(manager, method.returnType))) + switch (manager->getSort(resolveAllTypedefs(manager, type))) { case codemaker::UnoType::Sort::Void: - buf.append('v'); + buffer.append('v'); break; case codemaker::UnoType::Sort::Boolean: case codemaker::UnoType::Sort::Byte: @@ -262,101 +264,328 @@ OString computeSignature(rtl::Reference const& manager, case codemaker::UnoType::Sort::UnsignedLong: case codemaker::UnoType::Sort::Char: case codemaker::UnoType::Sort::Enum: - buf.append('i'); + buffer.append('i'); break; case codemaker::UnoType::Sort::Hyper: case codemaker::UnoType::Sort::UnsignedHyper: - buf.append('j'); + buffer.append('j'); break; case codemaker::UnoType::Sort::Float: - buf.append('f'); + buffer.append('f'); break; case codemaker::UnoType::Sort::Double: - buf.append('d'); + buffer.append('d'); break; case codemaker::UnoType::Sort::String: case codemaker::UnoType::Sort::Type: case codemaker::UnoType::Sort::Any: case codemaker::UnoType::Sort::Sequence: case codemaker::UnoType::Sort::Interface: - buf.append("vi"); + buffer.append("vi"); break; case codemaker::UnoType::Sort::PlainStruct: case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct: { - switch (getKind(manager, method.returnType)) + switch (getKind(manager, type)) { case StructKind::Empty: break; case StructKind::I32: - buf.append('i'); + buffer.append('i'); break; case StructKind::I64: - buf.append('j'); + buffer.append('j'); break; case StructKind::F32: - buf.append('f'); + buffer.append('f'); break; case StructKind::F64: - buf.append('d'); + buffer.append('d'); break; case StructKind::General: - buf.append("vi"); + buffer.append("vi"); break; } break; } default: - throw CannotDumpException("unexpected entity \"" + method.returnType - + "\" in call to computeSignature"); + throw CannotDumpException("unexpected entity \"" + type + + "\" in call to appendCallSignatureReturnType"); } +} + +void appendCallSignatureParameter( + OStringBuffer& buffer, rtl::Reference const& manager, + unoidl::InterfaceTypeEntity::Method::Parameter::Direction direction, OUString const& type) +{ + if (direction == unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN) + { + switch (manager->getSort(resolveAllTypedefs(manager, type))) + { + case codemaker::UnoType::Sort::Boolean: + case codemaker::UnoType::Sort::Byte: + case codemaker::UnoType::Sort::Short: + case codemaker::UnoType::Sort::UnsignedShort: + case codemaker::UnoType::Sort::Long: + case codemaker::UnoType::Sort::UnsignedLong: + case codemaker::UnoType::Sort::Char: + case codemaker::UnoType::Sort::Enum: + case codemaker::UnoType::Sort::String: + case codemaker::UnoType::Sort::Type: + case codemaker::UnoType::Sort::Any: + case codemaker::UnoType::Sort::Sequence: + case codemaker::UnoType::Sort::PlainStruct: + case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct: + case codemaker::UnoType::Sort::Interface: + buffer.append('i'); + break; + case codemaker::UnoType::Sort::Hyper: + case codemaker::UnoType::Sort::UnsignedHyper: + buffer.append('j'); + break; + case codemaker::UnoType::Sort::Float: + buffer.append('f'); + break; + case codemaker::UnoType::Sort::Double: + buffer.append('d'); + break; + default: + throw CannotDumpException("unexpected entity \"" + type + + "\" in call to appendCallSignatureParameter"); + } + } + else + { + buffer.append('i'); + } +} + +OString computeGetterCallSignature(rtl::Reference const& manager, + unoidl::InterfaceTypeEntity::Attribute const& attribute) +{ + OStringBuffer buf; + appendCallSignatureReturnType(buf, manager, attribute.type); + buf.append('i'); + return buf.makeStringAndClear(); +} + +OString computeSetterCallSignature(rtl::Reference const& manager, + unoidl::InterfaceTypeEntity::Attribute const& attribute) +{ + OStringBuffer buf("vi"); + appendCallSignatureParameter( + buf, manager, unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN, attribute.type); + return buf.makeStringAndClear(); +} + +OString computeMethodCallSignature(rtl::Reference const& manager, + unoidl::InterfaceTypeEntity::Method const& method) +{ + OStringBuffer buf; + appendCallSignatureReturnType(buf, manager, method.returnType); buf.append('i'); for (auto const& param : method.parameters) { - if (param.direction == unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN) - { - switch (manager->getSort(resolveAllTypedefs(manager, param.type))) - { - case codemaker::UnoType::Sort::Boolean: - case codemaker::UnoType::Sort::Byte: - case codemaker::UnoType::Sort::Short: - case codemaker::UnoType::Sort::UnsignedShort: - case codemaker::UnoType::Sort::Long: - case codemaker::UnoType::Sort::UnsignedLong: - case codemaker::UnoType::Sort::Char: - case codemaker::UnoType::Sort::Enum: - case codemaker::UnoType::Sort::String: - case codemaker::UnoType::Sort::Type: - case codemaker::UnoType::Sort::Any: - case codemaker::UnoType::Sort::Sequence: - case codemaker::UnoType::Sort::PlainStruct: - case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct: - case codemaker::UnoType::Sort::Interface: - buf.append('i'); - break; - case codemaker::UnoType::Sort::Hyper: - case codemaker::UnoType::Sort::UnsignedHyper: - buf.append('j'); - break; - case codemaker::UnoType::Sort::Float: - buf.append('f'); - break; - case codemaker::UnoType::Sort::Double: - buf.append('d'); - break; - default: - throw CannotDumpException("unexpected entity \"" + param.type - + "\" in call to computeSignature"); - } - } - else - { - buf.append('i'); - } + appendCallSignatureParameter(buf, manager, param.direction, param.type); } return buf.makeStringAndClear(); } +void appendSlotSignatureOffsets(OStringBuffer& buffer, sal_Int32 functionOffset, + sal_Int32 vtableOffset) +{ + buffer.append(OString::number(functionOffset) + "_" + OString::number(vtableOffset)); +} + +void appendSlotSignatureReturnType(OStringBuffer& buffer, + rtl::Reference const& manager, OUString const& type) +{ + switch (manager->getSort(resolveAllTypedefs(manager, type))) + { + case codemaker::UnoType::Sort::Void: + buffer.append('v'); + break; + case codemaker::UnoType::Sort::Boolean: + case codemaker::UnoType::Sort::Byte: + case codemaker::UnoType::Sort::Short: + case codemaker::UnoType::Sort::UnsignedShort: + case codemaker::UnoType::Sort::Long: + case codemaker::UnoType::Sort::UnsignedLong: + case codemaker::UnoType::Sort::Char: + case codemaker::UnoType::Sort::Enum: + buffer.append('i'); + break; + case codemaker::UnoType::Sort::Hyper: + case codemaker::UnoType::Sort::UnsignedHyper: + buffer.append('j'); + break; + case codemaker::UnoType::Sort::Float: + buffer.append('f'); + break; + case codemaker::UnoType::Sort::Double: + buffer.append('d'); + break; + case codemaker::UnoType::Sort::String: + case codemaker::UnoType::Sort::Type: + case codemaker::UnoType::Sort::Any: + case codemaker::UnoType::Sort::Sequence: + case codemaker::UnoType::Sort::Interface: + buffer.append('I'); + break; + case codemaker::UnoType::Sort::PlainStruct: + case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct: + { + switch (getKind(manager, type)) + { + case StructKind::Empty: + break; + case StructKind::I32: + buffer.append('i'); + break; + case StructKind::I64: + buffer.append('j'); + break; + case StructKind::F32: + buffer.append('f'); + break; + case StructKind::F64: + buffer.append('d'); + break; + case StructKind::General: + buffer.append('I'); + break; + } + break; + } + default: + throw CannotDumpException("unexpected entity \"" + type + + "\" in call to appendSlotSignatureReturnType"); + } +} + +void appendSlotSignatureParameter( + OStringBuffer& buffer, rtl::Reference const& manager, + unoidl::InterfaceTypeEntity::Method::Parameter::Direction direction, OUString const& type) +{ + if (direction == unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN) + { + switch (manager->getSort(resolveAllTypedefs(manager, type))) + { + case codemaker::UnoType::Sort::Boolean: + case codemaker::UnoType::Sort::Byte: + case codemaker::UnoType::Sort::Short: + case codemaker::UnoType::Sort::UnsignedShort: + case codemaker::UnoType::Sort::Long: + case codemaker::UnoType::Sort::UnsignedLong: + case codemaker::UnoType::Sort::Char: + case codemaker::UnoType::Sort::Enum: + case codemaker::UnoType::Sort::String: + case codemaker::UnoType::Sort::Type: + case codemaker::UnoType::Sort::Any: + case codemaker::UnoType::Sort::Sequence: + case codemaker::UnoType::Sort::PlainStruct: + case codemaker::UnoType::Sort::InstantiatedPolymorphicStruct: + case codemaker::UnoType::Sort::Interface: + buffer.append('i'); + break; + case codemaker::UnoType::Sort::Hyper: + case codemaker::UnoType::Sort::UnsignedHyper: + buffer.append('j'); + break; + case codemaker::UnoType::Sort::Float: + buffer.append('f'); + break; + case codemaker::UnoType::Sort::Double: + buffer.append('d'); + break; + default: + throw CannotDumpException("unexpected entity \"" + type + + "\" in call to appendSlotSignatureParameter"); + } + } + else + { + buffer.append('i'); + } +} + +OString computeGetterSlotSignature(rtl::Reference const& manager, + unoidl::InterfaceTypeEntity::Attribute const& attribute, + sal_Int32 functionOffset, sal_Int32 vtableOffset) +{ + OStringBuffer buf; + appendSlotSignatureOffsets(buf, functionOffset, vtableOffset); + appendSlotSignatureReturnType(buf, manager, attribute.type); + return buf.makeStringAndClear(); +} + +OString computeSetterSlotSignature(rtl::Reference const& manager, + unoidl::InterfaceTypeEntity::Attribute const& attribute, + sal_Int32 functionOffset, sal_Int32 vtableOffset) +{ + OStringBuffer buf; + appendSlotSignatureOffsets(buf, functionOffset, vtableOffset); + buf.append('v'); + appendSlotSignatureParameter( + buf, manager, unoidl::InterfaceTypeEntity::Method::Parameter::DIRECTION_IN, attribute.type); + return buf.makeStringAndClear(); +} + +OString computeMethodSlotSignature(rtl::Reference const& manager, + unoidl::InterfaceTypeEntity::Method const& method, + sal_Int32 functionOffset, sal_Int32 vtableOffset) +{ + OStringBuffer buf; + appendSlotSignatureOffsets(buf, functionOffset, vtableOffset); + appendSlotSignatureReturnType(buf, manager, method.returnType); + for (auto const& param : method.parameters) + { + appendSlotSignatureParameter(buf, manager, param.direction, param.type); + } + return buf.makeStringAndClear(); +} + +void computeSlotSignatures(rtl::Reference const& manager, + unoidl::InterfaceTypeEntity const& interface, sal_Int32& functionOffset, + sal_Int32& vtableOffset, std::set& slotSignatures) +{ + auto const orgVtableOffset = vtableOffset; + auto firstBase = true; + for (auto const& base : interface.getDirectMandatoryBases()) + { + auto const ent = manager->getManager()->findEntity(base.name); + if (!ent.is() || ent->getSort() != unoidl::Entity::SORT_INTERFACE_TYPE) + { + throw CannotDumpException("unexpected base type \"" + base.name + + "\" in call to computeSlotSignatures"); + } + sal_Int32 freshFunctionOffset = 0; + computeSlotSignatures(manager, *static_cast(ent.get()), + firstBase ? functionOffset : freshFunctionOffset, vtableOffset, + slotSignatures); + vtableOffset += 4; + firstBase = false; + } + for (auto const& attr : interface.getDirectAttributes()) + { + slotSignatures.insert( + computeGetterSlotSignature(manager, attr, functionOffset, orgVtableOffset)); + ++functionOffset; + if (!attr.readOnly) + { + slotSignatures.insert( + computeSetterSlotSignature(manager, attr, functionOffset, orgVtableOffset)); + ++functionOffset; + } + } + for (auto const& meth : interface.getDirectMethods()) + { + slotSignatures.insert( + computeMethodSlotSignature(manager, meth, functionOffset, orgVtableOffset)); + ++functionOffset; + } +} + void appendRttiSymbolSegment(OStringBuffer& buffer, OUString const& id) { OString s(OUStringToOString(id, RTL_TEXTENCODING_ASCII_US)); @@ -384,7 +613,8 @@ OString computeRttiSymbol(std::vector const& path, OUString const& id) void scan(rtl::Reference const& manager, rtl::Reference const& cursor, std::vector& path, - std::set& signatures, std::set& rttis) + std::set& callSignatures, std::set& slotSignatures, + std::set& rttis) { assert(cursor.is()); for (;;) @@ -400,19 +630,31 @@ void scan(rtl::Reference const& manager, case unoidl::Entity::SORT_MODULE: path.push_back(id); scan(manager, static_cast(ent.get())->createCursor(), path, - signatures, rttis); + callSignatures, slotSignatures, rttis); path.pop_back(); break; case unoidl::Entity::SORT_EXCEPTION_TYPE: rttis.insert(computeRttiSymbol(path, id)); break; case unoidl::Entity::SORT_INTERFACE_TYPE: - for (auto const& meth : - static_cast(ent.get())->getDirectMethods()) + { + auto const ite = static_cast(ent.get()); + for (auto const& attr : ite->getDirectAttributes()) { - signatures.insert(computeSignature(manager, meth)); + callSignatures.insert(computeGetterCallSignature(manager, attr)); + if (!attr.readOnly) + { + callSignatures.insert(computeSetterCallSignature(manager, attr)); + } } + for (auto const& meth : ite->getDirectMethods()) + { + callSignatures.insert(computeMethodCallSignature(manager, meth)); + } + computeSlotSignatures(manager, *ite, o3tl::temporary(0), + o3tl::temporary(0), slotSignatures); break; + } default: break; } @@ -447,11 +689,12 @@ SAL_IMPLEMENT_MAIN() } } std::vector path; - std::set signatures; + std::set callSignatures; + std::set slotSignatures; std::set rttis; for (auto const& prov : mgr->getPrimaryProviders()) { - scan(mgr, prov->createRootCursor(), path, signatures, rttis); + scan(mgr, prov->createRootCursor(), path, callSignatures, slotSignatures, rttis); } std::ofstream cppOut(cppPathname, std::ios_base::out | std::ios_base::trunc); if (!cppOut) @@ -460,18 +703,20 @@ SAL_IMPLEMENT_MAIN() std::exit(EXIT_FAILURE); } cppOut << "#include \n" + "#include \n" "#include \n" "#include \n" "#include \n" - "#include \n"; - for (auto const& sig : signatures) + "#include \n" + "#include \n"; + for (auto const& sig : callSignatures) { cppOut << "extern \"C\" void callVirtualFunction_" << sig << "(sal_uInt32 target, sal_uInt64 const * arguments, void * returnValue);\n"; } cppOut << "void callVirtualFunction(std::string_view signature, sal_uInt32 target, " "sal_uInt64 const * arguments, void * returnValue) {\n"; - for (auto const& sig : signatures) + for (auto const& sig : callSignatures) { cppOut << " if (signature == \"" << sig << "\") {\n" << " callVirtualFunction_" << sig << "(target, arguments, returnValue);\n" @@ -481,6 +726,145 @@ SAL_IMPLEMENT_MAIN() cppOut << " throw css::uno::RuntimeException(\"Wasm bridge cannot call virtual function " "with signature \" + OUString::fromUtf8(signature));\n" "}\n"; + if (!slotSignatures.empty()) + { + cppOut << "namespace {\n"; + } + for (auto const& sig : slotSignatures) + { + auto const i1 = sig.indexOf('_'); + assert(i1 != -1); + sal_Int32 i2 = i1 + 1; + for (;; ++i2) + { + assert(i2 < sig.getLength()); + if (!rtl::isAsciiDigit(static_cast(sig[i2]))) + { + break; + } + } + assert(i2 != i1); + cppOut << "extern \"C\" "; + switch (sig[i2]) + { + case 'd': + cppOut << "double"; + break; + case 'f': + cppOut << "float"; + break; + case 'i': + cppOut << "unsigned"; + break; + case 'j': + cppOut << "unsigned long long"; + break; + default: + cppOut << "void"; + break; + } + cppOut << " vtableSlotFunction_" << sig << "("; + if (sig[i2] == 'I') + { + cppOut << "unsigned indirectRet, "; + } + cppOut << "unsigned thisPtr"; + for (sal_Int32 i = i2 + 1; i != sig.getLength(); ++i) + { + cppOut << ", "; + switch (sig[i]) + { + case 'd': + cppOut << "double"; + break; + case 'f': + cppOut << "float"; + break; + case 'i': + cppOut << "unsigned"; + break; + case 'j': + cppOut << "unsigned long long"; + break; + default: + O3TL_UNREACHABLE; + } + cppOut << " arg" << (i - i2); + } + cppOut << ") { "; + switch (sig[i2]) + { + case 'd': + cppOut << "return std::bit_cast(static_cast("; + break; + case 'f': + cppOut << "return std::bit_cast(static_cast("; + break; + case 'i': + cppOut << "return static_cast("; + break; + case 'j': + cppOut << "return static_cast("; + break; + } + cppOut << "vtableCall(" << sig.subView(0, i1) << ", " + << sig.subView(i1 + 1, i2 - (i1 + 1)) << ", thisPtr, {"; + for (sal_Int32 i = i2 + 1; i != sig.getLength(); ++i) + { + if (i != i2 + 1) + { + cppOut << ", "; + } + cppOut << "sal_uInt64("; + switch (sig[i]) + { + case 'd': + cppOut << "std::bit_cast("; + break; + case 'f': + cppOut << "std::bit_cast("; + break; + } + cppOut << "arg" << (i - i2) << ")"; + switch (sig[i]) + { + case 'd': + case 'f': + cppOut << ")"; + break; + } + } + cppOut << "}, " + << (sig[i2] == 'I' ? "indirectRet" : "reinterpret_cast(nullptr)") + << ")"; + switch (sig[i2]) + { + case 'd': + case 'f': + cppOut << "))"; + break; + case 'i': + case 'j': + cppOut << ")"; + break; + } + cppOut << "; }\n"; + } + if (!slotSignatures.empty()) + { + cppOut << "}\n"; + } + cppOut << "void const * getVtableSlotFunction(std::string_view signature) {\n"; + for (auto const& sig : slotSignatures) + { + cppOut << " if (signature == \"" << sig << "\") {\n" + << " return reinterpret_cast(vtableSlotFunction_" << sig + << ");\n" + << " }\n"; + } + cppOut << " throw css::uno::RuntimeException(\"Wasm bridge cannot fill virtual function " + "slot with signature \" + OUString::fromUtf8(signature));\n" + "}\n"; cppOut.close(); if (!cppOut) { @@ -495,11 +879,11 @@ SAL_IMPLEMENT_MAIN() } asmOut << "\t.text\n" "\t.tabletype __indirect_function_table, funcref\n"; - for (auto const& sig : signatures) + for (auto const& sig : callSignatures) { asmOut << "\t.functype callVirtualFunction_" << sig << " (i32, i32, i32) -> ()\n"; } - for (auto const& sig : signatures) + for (auto const& sig : callSignatures) { asmOut << "\t.section .text.callVirtualFunction_" << sig << ",\"\",@\n" diff --git a/unotest/source/embindtest/embindtest.component b/unotest/source/embindtest/embindtest.component index 57a89249e8c0..f1106d3bc96a 100644 --- a/unotest/source/embindtest/embindtest.component +++ b/unotest/source/embindtest/embindtest.component @@ -12,6 +12,11 @@ environment="@CPPU_ENV@" loader="com.sun.star.loader.SharedLibrary" xmlns="http://openoffice.org/2010/uno-components"> + + + diff --git a/unotest/source/embindtest/embindtest.cxx b/unotest/source/embindtest/embindtest.cxx index 929db82e8900..81ede0e9cf93 100644 --- a/unotest/source/embindtest/embindtest.cxx +++ b/unotest/source/embindtest/embindtest.cxx @@ -9,6 +9,10 @@ #include +#include + +#include +#include #include #include #include @@ -26,9 +30,14 @@ #include #include #include +#include #include #include #include +#include +#include +#include +#include namespace com::sun::star::uno { @@ -601,6 +610,244 @@ class Test : public cppu::WeakImplHelper OUString stringAttribute_; }; + +class BridgeTest : public cppu::WeakImplHelper +{ +public: + explicit BridgeTest(css::uno::Reference const& context) + : context_(context) + { + } + +private: + css::uno::Any SAL_CALL + execute(css::uno::Sequence const& Arguments) override + { + if (Arguments.hasElements()) + { + throw css::lang::IllegalArgumentException(u"BridgeTest execute args not empty"_ustr, {}, + 0); + } + auto const envCppOrig = css::uno::Environment::getCurrent(); + css::uno::Environment envUno; + uno_createEnvironment(reinterpret_cast(&envUno), + u"" UNO_LB_UNO ""_ustr.pData, nullptr); + css::uno::Mapping cpp2uno(envCppOrig.get(), envUno.get()); + css::uno::Environment envCpp; + if (!cpp2uno.is()) + { + throw css::uno::RuntimeException(u"cannot get C++ to UNO mapping"_ustr); + } + uno_createEnvironment(reinterpret_cast(&envCpp), + envCppOrig.getTypeName().pData, nullptr); + css::uno::Mapping uno2cpp(envUno.get(), envCpp.get()); + if (!uno2cpp.is()) + { + throw css::uno::RuntimeException(u"cannot get UNO to C++ mapping"_ustr); + } + css::uno::UnoInterfaceReference ifcUno; + cpp2uno.mapInterface(reinterpret_cast(&ifcUno.m_pUnoI), + org::libreoffice::embindtest::Test::get(context_).get(), + cppu::UnoType::get()); + if (!ifcUno.is()) + { + throw css::uno::RuntimeException(u"cannot map from C++ to UNO"_ustr); + } + css::uno::Reference ifcCpp; + uno2cpp.mapInterface(reinterpret_cast(&ifcCpp), ifcUno.get(), + cppu::UnoType::get()); + if (!ifcCpp.is()) + { + throw css::uno::RuntimeException(u"cannot map from UNO to C++"_ustr); + } + { + auto const val = ifcCpp->getBoolean(); + assert(val); + auto const ok = ifcCpp->isBoolean(val); + assert(ok == css::uno::Any(true)); + } + { + auto const val = ifcCpp->getByte(); + assert(val == -12); + auto const ok = ifcCpp->isByte(val); + assert(ok == css::uno::Any(true)); + } + { + auto const val = ifcCpp->getShort(); + assert(val == -1234); + auto const ok = ifcCpp->isShort(val); + assert(ok == css::uno::Any(true)); + } + { + auto const val = ifcCpp->getUnsignedShort(); + assert(val == 54321); + auto const ok = ifcCpp->isUnsignedShort(val); + assert(ok == css::uno::Any(true)); + } + { + auto const val = ifcCpp->getLong(); + assert(val == -123456); + auto const ok = ifcCpp->isLong(val); + assert(ok == css::uno::Any(true)); + } + { + auto const val = ifcCpp->getUnsignedLong(); + assert(val == 3456789012); + auto const ok = ifcCpp->isUnsignedLong(val); + assert(ok == css::uno::Any(true)); + } + { + auto const val = ifcCpp->getHyper(); + assert(val == -123456789); + auto const ok = ifcCpp->isHyper(val); + assert(ok == css::uno::Any(true)); + } + { + auto const val = ifcCpp->getUnsignedHyper(); + assert(val == 9876543210); + auto const ok = ifcCpp->isUnsignedHyper(val); + assert(ok == css::uno::Any(true)); + } + { + auto const val = ifcCpp->getFloat(); + assert(val == -10.25); + auto const ok = ifcCpp->isFloat(val); + assert(ok == css::uno::Any(true)); + } + { + auto const val = ifcCpp->getDouble(); + assert(val == 100.5); + auto const ok = ifcCpp->isDouble(val); + assert(ok == css::uno::Any(true)); + } + { + auto const val = ifcCpp->getChar(); + assert(val == u'Ö'); + auto const ok = ifcCpp->isChar(val); + assert(ok == css::uno::Any(true)); + } + { + auto const val = ifcCpp->getString(); + assert(val == u"hä"_ustr); + auto const ok = ifcCpp->isString(val); + assert(ok == css::uno::Any(true)); + } + { + auto const val = ifcCpp->getType(); + assert(val == cppu::UnoType::get()); + auto const ok = ifcCpp->isType(val); + assert(ok == css::uno::Any(true)); + } + { + auto const val = ifcCpp->getEnum(); + assert(val == org::libreoffice::embindtest::Enum_E_2); + auto const ok = ifcCpp->isEnum(val); + assert(ok == css::uno::Any(true)); + } + { + auto const val = ifcCpp->getStruct(); + assert((val == org::libreoffice::embindtest::Struct{ -123456, 100.5, u"hä"_ustr })); + auto const ok = ifcCpp->isStruct(val); + assert(ok == css::uno::Any(true)); + } + { + auto const val = ifcCpp->getStructLong(); + assert(val == org::libreoffice::embindtest::StructLong{ -123456 }); + auto const ok = ifcCpp->isStructLong(val); + assert(ok == css::uno::Any(true)); + } + { + auto const val = ifcCpp->getStructString(); + assert(val == org::libreoffice::embindtest::StructString{ u"hä"_ustr }); + auto const ok = ifcCpp->isStructString(val); + assert(ok == css::uno::Any(true)); + } + { + auto const val = ifcCpp->getAnyVoid(); + assert(val == css::uno::Any()); + auto const ok = ifcCpp->isAnyVoid(val); + assert(ok == css::uno::Any(true)); + } + { + auto const val = ifcCpp->getSequenceBoolean(); + assert((val == css::uno::Sequence{ true, true, false })); + auto const ok = ifcCpp->isSequenceBoolean(val); + assert(ok == css::uno::Any(true)); + } + { + auto const val = ifcCpp->getNull(); + assert(val == css::uno::Reference()); + auto const ok = ifcCpp->isNull(val); + assert(ok == css::uno::Any(true)); + } + { + sal_Bool value1; + sal_Int8 value2; + sal_Int16 value3; + sal_uInt16 value4; + sal_Int32 value5; + sal_uInt32 value6; + sal_Int64 value7; + sal_uInt64 value8; + float value9; + double value10; + sal_Unicode value11; + OUString value12; + css::uno::Type value13; + css::uno::Any value14; + css::uno::Sequence value15; + org::libreoffice::embindtest::Enum value16; + org::libreoffice::embindtest::Struct value17; + css::uno::Reference value18; + ifcCpp->getOut(value1, value2, value3, value4, value5, value6, value7, value8, value9, + value10, value11, value12, value13, value14, value15, value16, value17, + value18); + assert(value1); + assert(value2 == -12); + assert(value3 == -1234); + assert(value4 == 54321); + assert(value5 == -123456); + assert(value6 == 3456789012); + assert(value7 == -123456789); + assert(value8 == 9876543210); + assert(value9 == -10.25); + assert(value10 == 100.5); + assert(value11 == u'Ö'); + assert(value12 == u"hä"_ustr); + assert(value13 == cppu::UnoType::get()); + assert(value14 == css::uno::Any(sal_Int32(-123456))); + assert((value15 + == css::uno::Sequence{ u"foo"_ustr, u"barr"_ustr, u"bazzz"_ustr })); + assert(value16 == org::libreoffice::embindtest::Enum_E_2); + assert((value17 == org::libreoffice::embindtest::Struct{ -123456, 100.5, u"hä"_ustr })); + assert(value18 == ifcCpp); + } + try + { + ifcCpp->throwRuntimeException(); + assert(false); + } + catch (css::uno::RuntimeException& e) + { + assert(e.Message.startsWith("test")); + } + { + ifcCpp->setStringAttribute(u"hä"_ustr); + auto const val = ifcCpp->getStringAttribute(); + assert(val == u"hä"_ustr); + } + return css::uno::Any(true); + } + + css::uno::Reference context_; +}; +} + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +org_libreoffice_comp_embindtest_BridgeTest_get_implementation( + css::uno::XComponentContext* context, css::uno::Sequence const&) +{ + return cppu::acquire(new BridgeTest(context)); } extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* diff --git a/unotest/source/embindtest/embindtest.js b/unotest/source/embindtest/embindtest.js index d47fed4703ab..5c2451377550 100644 --- a/unotest/source/embindtest/embindtest.js +++ b/unotest/source/embindtest/embindtest.js @@ -1107,6 +1107,16 @@ Module.addOnPostRun(function() { console.assert(ret.get() === 'hä'); ret.delete(); } + { + const args = new Module.uno_Sequence_com$sun$star$beans$NamedValue( + 0, Module.uno_Sequence.FromSize); + const ret = + Module.uno.org.libreoffice.embindtest.BridgeTest(Module.getUnoComponentContext()). + execute(args); + args.delete(); + console.assert(ret.get() === true); + ret.delete(); + } }); /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */