359 lines
13 KiB
C++
359 lines
13 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* 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/.
|
|
*/
|
|
|
|
#include <sal/config.h>
|
|
|
|
#include <exception>
|
|
#include <typeinfo>
|
|
#include <vector>
|
|
|
|
#include <alloca.h>
|
|
|
|
#include <com/sun/star/uno/Exception.hpp>
|
|
#include <com/sun/star/uno/RuntimeException.hpp>
|
|
#include <com/sun/star/uno/genfunc.hxx>
|
|
#include <cppu/unotype.hxx>
|
|
#include <o3tl/runtimetooustring.hxx>
|
|
#include <o3tl/temporary.hxx>
|
|
#include <o3tl/unreachable.hxx>
|
|
#include <rtl/strbuf.hxx>
|
|
#include <typelib/typeclass.h>
|
|
#include <typelib/typedescription.h>
|
|
#include <typelib/typedescription.hxx>
|
|
#include <uno/any2.h>
|
|
#include <uno/data.h>
|
|
|
|
#include <bridge.hxx>
|
|
#include <types.hxx>
|
|
#include <unointerfaceproxy.hxx>
|
|
#include <vtables.hxx>
|
|
#include <wasm/generated.hxx>
|
|
|
|
#include "abi.hxx"
|
|
|
|
namespace
|
|
{
|
|
void call(bridges::cpp_uno::shared::UnoInterfaceProxy* proxy,
|
|
bridges::cpp_uno::shared::VtableSlot slot, typelib_TypeDescriptionReference* returnType,
|
|
sal_Int32 count, typelib_MethodParameter* parameters, void* returnValue, void** arguments,
|
|
uno_Any** exception)
|
|
{
|
|
css::uno::TypeDescription rtd(returnType);
|
|
auto const retConv = bridges::cpp_uno::shared::relatesToInterfaceType(rtd.get());
|
|
auto const ret = retConv ? alloca(rtd.get()->nSize) : returnValue;
|
|
OStringBuffer sig;
|
|
std::vector<sal_uInt64> args;
|
|
switch (rtd.get()->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("vi");
|
|
args.push_back(reinterpret_cast<sal_uInt32>(ret));
|
|
break;
|
|
case typelib_TypeClass_STRUCT:
|
|
{
|
|
switch (abi_wasm::getKind(
|
|
reinterpret_cast<typelib_CompoundTypeDescription const*>(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("vi");
|
|
args.push_back(reinterpret_cast<sal_uInt32>(ret));
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
O3TL_UNREACHABLE;
|
|
}
|
|
sig.append('i');
|
|
sal_uInt32 const* const* thisPtr
|
|
= reinterpret_cast<sal_uInt32 const* const*>(proxy->getCppI()) + slot.offset;
|
|
args.push_back(reinterpret_cast<sal_uInt32>(thisPtr));
|
|
std::vector<void*> cppArgs(count);
|
|
std::vector<css::uno::TypeDescription> ptds(count);
|
|
for (sal_Int32 i = 0; i != count; ++i)
|
|
{
|
|
if (!parameters[i].bOut && bridges::cpp_uno::shared::isSimpleType(parameters[i].pTypeRef))
|
|
{
|
|
switch (parameters[i].pTypeRef->eTypeClass)
|
|
{
|
|
case typelib_TypeClass_BOOLEAN:
|
|
sig.append('i');
|
|
args.push_back(*reinterpret_cast<sal_Bool const*>(arguments[i]));
|
|
break;
|
|
case typelib_TypeClass_BYTE:
|
|
sig.append('i');
|
|
args.push_back(*reinterpret_cast<sal_Int8 const*>(arguments[i]));
|
|
break;
|
|
case typelib_TypeClass_SHORT:
|
|
sig.append('i');
|
|
args.push_back(*reinterpret_cast<sal_Int16 const*>(arguments[i]));
|
|
break;
|
|
case typelib_TypeClass_UNSIGNED_SHORT:
|
|
sig.append('i');
|
|
args.push_back(*reinterpret_cast<sal_uInt16 const*>(arguments[i]));
|
|
break;
|
|
case typelib_TypeClass_LONG:
|
|
case typelib_TypeClass_ENUM:
|
|
sig.append('i');
|
|
args.push_back(*reinterpret_cast<sal_Int32 const*>(arguments[i]));
|
|
break;
|
|
case typelib_TypeClass_UNSIGNED_LONG:
|
|
sig.append('i');
|
|
args.push_back(*reinterpret_cast<sal_uInt32 const*>(arguments[i]));
|
|
break;
|
|
case typelib_TypeClass_HYPER:
|
|
sig.append('j');
|
|
args.push_back(*reinterpret_cast<sal_Int64 const*>(arguments[i]));
|
|
break;
|
|
case typelib_TypeClass_UNSIGNED_HYPER:
|
|
sig.append('j');
|
|
args.push_back(*reinterpret_cast<sal_uInt64 const*>(arguments[i]));
|
|
break;
|
|
case typelib_TypeClass_FLOAT:
|
|
sig.append('f');
|
|
args.push_back(*reinterpret_cast<sal_uInt32 const*>(arguments[i]));
|
|
break;
|
|
case typelib_TypeClass_DOUBLE:
|
|
sig.append('d');
|
|
args.push_back(*reinterpret_cast<sal_uInt64 const*>(arguments[i]));
|
|
break;
|
|
case typelib_TypeClass_CHAR:
|
|
sig.append('i');
|
|
args.push_back(*reinterpret_cast<sal_Unicode const*>(arguments[i]));
|
|
break;
|
|
default:
|
|
O3TL_UNREACHABLE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sig.append('i');
|
|
css::uno::TypeDescription ptd(parameters[i].pTypeRef);
|
|
if (!parameters[i].bIn)
|
|
{
|
|
cppArgs[i] = alloca(ptd.get()->nSize);
|
|
uno_constructData(cppArgs[i], ptd.get());
|
|
ptds[i] = ptd;
|
|
args.push_back(reinterpret_cast<sal_uInt32>(cppArgs[i]));
|
|
}
|
|
else if (bridges::cpp_uno::shared::relatesToInterfaceType(ptd.get()))
|
|
{
|
|
cppArgs[i] = alloca(ptd.get()->nSize);
|
|
uno_copyAndConvertData(cppArgs[i], arguments[i], ptd.get(),
|
|
proxy->getBridge()->getUno2Cpp());
|
|
ptds[i] = ptd;
|
|
args.push_back(reinterpret_cast<sal_uInt32>(cppArgs[i]));
|
|
}
|
|
else
|
|
{
|
|
args.push_back(reinterpret_cast<sal_uInt32>(arguments[i]));
|
|
}
|
|
}
|
|
}
|
|
try
|
|
{
|
|
try
|
|
{
|
|
callVirtualFunction(sig, (*thisPtr)[slot.index], args.data(), ret);
|
|
}
|
|
catch (css::uno::Exception&)
|
|
{
|
|
throw;
|
|
}
|
|
catch (std::exception& e)
|
|
{
|
|
throw css::uno::RuntimeException("C++ code threw "
|
|
+ o3tl::runtimeToOUString(typeid(e).name()) + ": "
|
|
+ o3tl::runtimeToOUString(e.what()));
|
|
}
|
|
catch (...)
|
|
{
|
|
throw css::uno::RuntimeException("C++ code threw unknown exception");
|
|
}
|
|
}
|
|
catch (css::uno::Exception&)
|
|
{
|
|
__cxxabiv1::__cxa_exception* header
|
|
= reinterpret_cast<__cxxabiv1::__cxa_eh_globals*>(__cxxabiv1::__cxa_get_globals())
|
|
->caughtExceptions;
|
|
abi_wasm::mapException(header, __cxxabiv1::__cxa_current_exception_type(), *exception,
|
|
proxy->getBridge()->getCpp2Uno());
|
|
for (sal_Int32 i = 0; i != count; ++i)
|
|
{
|
|
if (cppArgs[i] != nullptr)
|
|
{
|
|
uno_destructData(cppArgs[i], ptds[i].get(),
|
|
reinterpret_cast<uno_ReleaseFunc>(css::uno::cpp_release));
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
*exception = nullptr;
|
|
for (sal_Int32 i = 0; i != count; ++i)
|
|
{
|
|
if (cppArgs[i] != nullptr)
|
|
{
|
|
if (parameters[i].bOut)
|
|
{
|
|
if (parameters[i].bIn)
|
|
{
|
|
uno_destructData(arguments[i], ptds[i].get(), nullptr);
|
|
}
|
|
uno_copyAndConvertData(arguments[i], cppArgs[i], ptds[i].get(),
|
|
proxy->getBridge()->getCpp2Uno());
|
|
}
|
|
uno_destructData(cppArgs[i], ptds[i].get(),
|
|
reinterpret_cast<uno_ReleaseFunc>(css::uno::cpp_release));
|
|
}
|
|
}
|
|
if (retConv)
|
|
{
|
|
uno_copyAndConvertData(returnValue, ret, rtd.get(), proxy->getBridge()->getCpp2Uno());
|
|
uno_destructData(ret, rtd.get(), reinterpret_cast<uno_ReleaseFunc>(css::uno::cpp_release));
|
|
}
|
|
}
|
|
}
|
|
|
|
namespace bridges::cpp_uno::shared
|
|
{
|
|
void unoInterfaceProxyDispatch(uno_Interface* pUnoI, const typelib_TypeDescription* pMemberDescr,
|
|
void* pReturn, void* pArgs[], uno_Any** ppException)
|
|
{
|
|
bridges::cpp_uno::shared::UnoInterfaceProxy* pThis
|
|
= static_cast<bridges::cpp_uno::shared::UnoInterfaceProxy*>(pUnoI);
|
|
|
|
switch (pMemberDescr->eTypeClass)
|
|
{
|
|
case typelib_TypeClass_INTERFACE_ATTRIBUTE:
|
|
{
|
|
auto const atd
|
|
= reinterpret_cast<typelib_InterfaceAttributeTypeDescription const*>(pMemberDescr);
|
|
VtableSlot slot(getVtableSlot(atd));
|
|
if (pReturn == nullptr)
|
|
{
|
|
slot.index += 1;
|
|
call(pThis, slot, cppu::UnoType<void>::get().getTypeLibType(), 1,
|
|
&o3tl::temporary(
|
|
typelib_MethodParameter{ nullptr, atd->pAttributeTypeRef, true, false }),
|
|
pReturn, pArgs, ppException);
|
|
}
|
|
else
|
|
{
|
|
call(pThis, slot, atd->pAttributeTypeRef, 0, nullptr, pReturn, pArgs, ppException);
|
|
}
|
|
break;
|
|
}
|
|
case typelib_TypeClass_INTERFACE_METHOD:
|
|
{
|
|
VtableSlot aVtableSlot(getVtableSlot(
|
|
reinterpret_cast<typelib_InterfaceMethodTypeDescription const*>(pMemberDescr)));
|
|
|
|
switch (aVtableSlot.index)
|
|
{
|
|
case 1: // acquire uno interface
|
|
(*pUnoI->acquire)(pUnoI);
|
|
*ppException = 0;
|
|
break;
|
|
case 2: // release uno interface
|
|
(*pUnoI->release)(pUnoI);
|
|
*ppException = 0;
|
|
break;
|
|
case 0: // queryInterface() opt
|
|
{
|
|
typelib_TypeDescription* pTD = 0;
|
|
TYPELIB_DANGER_GET(
|
|
&pTD, reinterpret_cast<css::uno::Type*>(pArgs[0])->getTypeLibType());
|
|
if (pTD)
|
|
{
|
|
uno_Interface* pInterface = 0;
|
|
(*pThis->getBridge()->getUnoEnv()->getRegisteredInterface)(
|
|
pThis->getBridge()->getUnoEnv(), (void**)&pInterface, pThis->oid.pData,
|
|
(typelib_InterfaceTypeDescription*)pTD);
|
|
|
|
if (pInterface)
|
|
{
|
|
::uno_any_construct(reinterpret_cast<uno_Any*>(pReturn), &pInterface,
|
|
pTD, 0);
|
|
(*pInterface->release)(pInterface);
|
|
TYPELIB_DANGER_RELEASE(pTD);
|
|
*ppException = 0;
|
|
break;
|
|
}
|
|
TYPELIB_DANGER_RELEASE(pTD);
|
|
}
|
|
} // else perform queryInterface()
|
|
[[fallthrough]];
|
|
default:
|
|
{
|
|
auto const mtd
|
|
= reinterpret_cast<typelib_InterfaceMethodTypeDescription const*>(
|
|
pMemberDescr);
|
|
call(pThis, aVtableSlot, mtd->pReturnTypeRef, mtd->nParams, mtd->pParams,
|
|
pReturn, pArgs, ppException);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
::com::sun::star::uno::RuntimeException aExc(
|
|
"illegal member type description!",
|
|
::com::sun::star::uno::Reference<::com::sun::star::uno::XInterface>());
|
|
|
|
css::uno::Type const& rExcType = cppu::UnoType<decltype(aExc)>::get();
|
|
// binary identical null reference
|
|
::uno_type_any_construct(*ppException, &aExc, rExcType.getTypeLibType(), 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace bridges::cpp_uno::shared
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|