From 8a56900c61b82e9571d64add833784acfb628853 Mon Sep 17 00:00:00 2001 From: Jan-Marek Glogowski Date: Sat, 5 Sep 2020 15:20:51 +0200 Subject: WIN bridges: unify cpp2uno common code Change-Id: I614fb662b164b0af9ca03c3ab8006b9105380112 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/102865 Tested-by: Jenkins Reviewed-by: Jan-Marek Glogowski --- bridges/Library_cpp_uno.mk | 1 + bridges/inc/msvc/cpp2uno.hxx | 31 ++ bridges/source/cpp_uno/msvc_shared/cpp2uno.cxx | 354 +++++++++++++++++++++ .../source/cpp_uno/msvc_win32_intel/cpp2uno.cxx | 319 +------------------ .../source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx | 303 +----------------- 5 files changed, 390 insertions(+), 618 deletions(-) create mode 100644 bridges/inc/msvc/cpp2uno.hxx create mode 100644 bridges/source/cpp_uno/msvc_shared/cpp2uno.cxx (limited to 'bridges') diff --git a/bridges/Library_cpp_uno.mk b/bridges/Library_cpp_uno.mk index 67a66cdadfb5..e1cf6f52cff2 100644 --- a/bridges/Library_cpp_uno.mk +++ b/bridges/Library_cpp_uno.mk @@ -273,6 +273,7 @@ $(eval $(call gb_Library_add_exception_objects,$(gb_CPPU_ENV)_uno,\ ifeq ($(COM),MSC) $(eval $(call gb_Library_add_exception_objects,$(gb_CPPU_ENV)_uno,\ + bridges/source/cpp_uno/msvc_shared/cpp2uno \ bridges/source/cpp_uno/msvc_shared/except \ )) endif diff --git a/bridges/inc/msvc/cpp2uno.hxx b/bridges/inc/msvc/cpp2uno.hxx new file mode 100644 index 000000000000..47091ed3bce3 --- /dev/null +++ b/bridges/inc/msvc/cpp2uno.hxx @@ -0,0 +1,31 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#define WIN32_LEAN_AND_MEAN +#include + +#include +#include + +typelib_TypeClass __cdecl cpp_mediate(void** pCallStack, sal_Int32 nFunctionIndex, + sal_Int32 nVtableOffset, sal_Int64* const pRegisterReturn); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/msvc_shared/cpp2uno.cxx b/bridges/source/cpp_uno/msvc_shared/cpp2uno.cxx new file mode 100644 index 000000000000..51186d1859fc --- /dev/null +++ b/bridges/source/cpp_uno/msvc_shared/cpp2uno.cxx @@ -0,0 +1,354 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include + +#include +#include +#include +#include + +#include "bridge.hxx" +#include "cppinterfaceproxy.hxx" +#include "types.hxx" +#include "vtablefactory.hxx" + +#include +#include + +using namespace ::com::sun::star; + +static typelib_TypeClass +cpp2uno_call(bridges::cpp_uno::shared::CppInterfaceProxy* pThis, + const typelib_TypeDescription* pMemberTD, + typelib_TypeDescriptionReference* pReturnTypeRef, // nullptr indicates void return + const sal_Int32 nParams, typelib_MethodParameter* pParams, void** pCallStack, + void** const pReturnAddr) +{ + // return type + typelib_TypeDescription* pReturnTD = nullptr; + if (pReturnTypeRef) + TYPELIB_DANGER_GET(&pReturnTD, pReturnTypeRef); + + // if we don't return via register, the first stack parameter is the return value + int nFirstRealParam = 2; + if (pReturnAddr == pCallStack) + ++nFirstRealParam; + + void* pUnoReturn = nullptr; + // complex return ptr: if != nullptr && != pUnoReturn, reconversion needed + void* pCppReturn = nullptr; + + if (pReturnTD) + { + if (bridges::cpp_uno::shared::isSimpleType(pReturnTD)) + pUnoReturn = pReturnAddr; + else + { + pCppReturn = pCallStack[nFirstRealParam++]; + pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType(pReturnTD) + ? alloca(pReturnTD->nSize) + : pCppReturn); + } + } + + // parameters passed to the UNO function + void** pUnoArgs = static_cast(alloca(sizeof(void*) * nParams)); + + // parameters received from C++ + void** pCppArgs = static_cast(alloca(sizeof(void*) * nParams)); + + // TODO: switch to typedef std::pair ReconversationInfo; + sal_Int32 nTempIndex = 0; + // indexes of values this have to be converted (interface conversion C++<=>UNO) + sal_Int32* pTempIndexes = static_cast(alloca(sizeof(sal_Int32) * nParams)); + // type descriptions for reconversions + typelib_TypeDescription** ppTempParamTD + = static_cast(alloca(sizeof(void*) * nParams)); + + for (std::pair p(0, pCallStack + nFirstRealParam); p.first < nParams; + ++p.first, ++p.second) + { + const auto& nPos = p.first; + auto& pCppIncomingParams = p.second; + + const typelib_MethodParameter& rParam = pParams[nPos]; + typelib_TypeDescription* pParamTD = nullptr; + TYPELIB_DANGER_GET(&pParamTD, rParam.pTypeRef); + + if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType(pParamTD)) + { + pCppArgs[nPos] = pCppIncomingParams; + pUnoArgs[nPos] = pCppIncomingParams; + if (sizeof(void*) == sizeof(sal_Int32)) // acccount 64bit types on 32bit arch + { + switch (pParamTD->eTypeClass) + { + case typelib_TypeClass_HYPER: + case typelib_TypeClass_UNSIGNED_HYPER: + case typelib_TypeClass_DOUBLE: + ++pCppIncomingParams; + break; + default: + break; + } + } + TYPELIB_DANGER_RELEASE(pParamTD); + } + else // ptr to complex value | ref + { + pCppArgs[nPos] = *pCppIncomingParams; + + if (!rParam.bIn) // is pure out + { + // UNO out is unconstructed memory + pUnoArgs[nPos] = alloca(pParamTD->nSize); + // pParamTD will be released at reconversion + pTempIndexes[nTempIndex] = nPos; + ppTempParamTD[nTempIndex++] = pParamTD; + } + // is in/inout + else if (bridges::cpp_uno::shared::relatesToInterfaceType(pParamTD)) + { + ::uno_copyAndConvertData(pUnoArgs[nPos] = alloca(pParamTD->nSize), + *pCppIncomingParams, pParamTD, + pThis->getBridge()->getCpp2Uno()); + // pParamTD will be released at reconversion + pTempIndexes[nTempIndex] = nPos; + ppTempParamTD[nTempIndex++] = pParamTD; + } + else // direct way + { + pUnoArgs[nPos] = *pCppIncomingParams; + TYPELIB_DANGER_RELEASE(pParamTD); + } + } + } + + // ExceptionHolder + uno_Any aUnoExc; // Any will be constructed by callee + uno_Any* pUnoExc = &aUnoExc; + + // invoke UNO dispatch call + pThis->getUnoI()->pDispatcher(pThis->getUnoI(), pMemberTD, pUnoReturn, pUnoArgs, &pUnoExc); + + // in case an exception occurred... + if (pUnoExc) + { + // destruct temporary in/inout params + while (nTempIndex--) + { + const sal_Int32 nIndex = pTempIndexes[nTempIndex]; + if (pParams[nIndex].bIn) // is in/inout => was constructed + ::uno_destructData(pUnoArgs[nIndex], ppTempParamTD[nTempIndex], nullptr); + TYPELIB_DANGER_RELEASE(ppTempParamTD[nTempIndex]); + } + if (pReturnTD) + TYPELIB_DANGER_RELEASE(pReturnTD); + + msvc_raiseException(&aUnoExc, pThis->getBridge()->getUno2Cpp()); // has to destruct the any + + // is here for dummy + return typelib_TypeClass_VOID; + } + else // no exception occurred... + { + // handle temporary params + while (nTempIndex--) + { + const sal_Int32 nIndex = pTempIndexes[nTempIndex]; + typelib_TypeDescription* pParamTD = ppTempParamTD[nTempIndex]; + + if (pParams[nIndex].bOut) // inout/out + { + // convert and assign + ::uno_destructData(pCppArgs[nIndex], pParamTD, uno::cpp_release); + ::uno_copyAndConvertData(pCppArgs[nIndex], pUnoArgs[nIndex], pParamTD, + pThis->getBridge()->getUno2Cpp()); + } + // destroy temp UNO param + ::uno_destructData(pUnoArgs[nIndex], pParamTD, nullptr); + + TYPELIB_DANGER_RELEASE(pParamTD); + } + + // handle return + if (pCppReturn) // has complex return + { + if (pUnoReturn != pCppReturn) // needs reconversion + { + ::uno_copyAndConvertData(pCppReturn, pUnoReturn, pReturnTD, + pThis->getBridge()->getUno2Cpp()); + // destroy temp UNO return + ::uno_destructData(pUnoReturn, pReturnTD, nullptr); + } + *pReturnAddr = pCppReturn; + } + + if (!pReturnTD) + return typelib_TypeClass_VOID; + else + { + typelib_TypeClass eRet = pReturnTD->eTypeClass; + TYPELIB_DANGER_RELEASE(pReturnTD); + return eRet; + } + } +} + +typelib_TypeClass __cdecl cpp_mediate(void** pCallStack, const sal_Int32 nFunctionIndex, + const sal_Int32 nVtableOffset, + sal_Int64* const pRegisterReturn) +{ + // pCallStack: + // x64: ret value, ret adr, this, [complex ret *], cpp params + // x86: ret adr, this, [complex ret *], cpp params + // + // pRegisterReturn is just set on x86 + // the return value is either the direct set for simply types, or it is set + // to "complex ret *" and the real return value is constructed at that memory. + + // if we don't return via register, the first stack parameter is the return value + void** const pReturnAddr + = pRegisterReturn ? reinterpret_cast(pRegisterReturn) : pCallStack; + + void* const pThis = static_cast(pCallStack[pRegisterReturn ? 1 : 2]) - nVtableOffset; + bridges::cpp_uno::shared::CppInterfaceProxy* pCppI + = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(pThis); + + typelib_InterfaceTypeDescription* pInterfaceTD = pCppI->getTypeDescr(); + + SAL_INFO("bridges", "cpp_vtable_call: pCallStack=[" + << std::hex << pCallStack[0] << "," << pCallStack[1] << "," + << pCallStack[2] << ",...], pThis=" << pThis << ", pCppI=" << pCppI + << std::dec << ", nFunctionIndex=" << nFunctionIndex + << ", nVtableOffset=" << nVtableOffset); + SAL_INFO("bridges", "name=" << OUString::unacquired(&pInterfaceTD->aBase.pTypeName)); + + if (nFunctionIndex >= pInterfaceTD->nMapFunctionIndexToMemberIndex) + { + OUString sError = "illegal " + OUString::unacquired(&pInterfaceTD->aBase.pTypeName) + + " vtable index " + OUString::number(nFunctionIndex) + "/" + + OUString::number(pInterfaceTD->nMapFunctionIndexToMemberIndex); + SAL_WARN("bridges", sError); + throw uno::RuntimeException(sError, reinterpret_cast(pThis)); + } + + // determine called method + sal_Int32 nMemberPos = pInterfaceTD->pMapFunctionIndexToMemberIndex[nFunctionIndex]; + assert(nMemberPos < pInterfaceTD->nAllMembers); + + uno::TypeDescription aMemberDescr(pInterfaceTD->ppAllMembers[nMemberPos]); + + SAL_INFO("bridges", "Calling " << OUString::unacquired(&aMemberDescr.get()->pTypeName)); + + typelib_TypeClass eRet = typelib_TypeClass_VOID; + switch (aMemberDescr.get()->eTypeClass) + { + case typelib_TypeClass_INTERFACE_ATTRIBUTE: + { + typelib_TypeDescriptionReference* pAttrTypeRef + = reinterpret_cast(aMemberDescr.get()) + ->pAttributeTypeRef; + + if (pInterfaceTD->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex) + { // is GET method + eRet = cpp2uno_call(pCppI, aMemberDescr.get(), pAttrTypeRef, 0, nullptr, pCallStack, + pReturnAddr); + } + else + { // is SET method + typelib_MethodParameter aParam; + aParam.pTypeRef = pAttrTypeRef; + aParam.bIn = true; + aParam.bOut = false; + + eRet = cpp2uno_call(pCppI, aMemberDescr.get(), nullptr, 1, &aParam, pCallStack, + pReturnAddr); + } + break; + } + case typelib_TypeClass_INTERFACE_METHOD: + { + // is METHOD + switch (nFunctionIndex) + { + // standard XInterface vtable calls + case 1: // acquire() + pCppI->acquireProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 2: // release() + pCppI->releaseProxy(); // non virtual call! + eRet = typelib_TypeClass_VOID; + break; + case 0: // queryInterface() opt + { + const unsigned int nCppStackPos = (pReturnAddr == pCallStack) ? 4 : 3; + typelib_TypeDescription* pQueryTD = nullptr; + TYPELIB_DANGER_GET( + &pQueryTD, + static_cast(pCallStack[nCppStackPos])->getTypeLibType()); + if (pQueryTD) + { + uno::XInterface* pInterface = nullptr; + + pCppI->getBridge()->getCppEnv()->getRegisteredInterface( + pCppI->getBridge()->getCppEnv(), reinterpret_cast(&pInterface), + pCppI->getOid().pData, + reinterpret_cast(pQueryTD)); + + if (pInterface) + { + const unsigned int nReturnAddrPos = nCppStackPos - 1; + ::uno_any_construct(static_cast(pCallStack[nReturnAddrPos]), + &pInterface, pQueryTD, uno::cpp_acquire); + pInterface->release(); + TYPELIB_DANGER_RELEASE(pQueryTD); + + *pReturnAddr = pCallStack[nReturnAddrPos]; + eRet = typelib_TypeClass_ANY; + break; + } + TYPELIB_DANGER_RELEASE(pQueryTD); + } + [[fallthrough]]; + } + default: // perform queryInterface() + { + typelib_InterfaceMethodTypeDescription* pMethodTD + = reinterpret_cast( + aMemberDescr.get()); + + eRet = cpp2uno_call(pCppI, aMemberDescr.get(), pMethodTD->pReturnTypeRef, + pMethodTD->nParams, pMethodTD->pParams, pCallStack, + pReturnAddr); + } + } + break; + } + default: + throw uno::RuntimeException("no member description found!", + reinterpret_cast(pThis)); + } + + return eRet; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/bridges/source/cpp_uno/msvc_win32_intel/cpp2uno.cxx b/bridges/source/cpp_uno/msvc_win32_intel/cpp2uno.cxx index 22e91e4ba8d3..0908c7666b50 100644 --- a/bridges/source/cpp_uno/msvc_win32_intel/cpp2uno.cxx +++ b/bridges/source/cpp_uno/msvc_win32_intel/cpp2uno.cxx @@ -31,330 +31,13 @@ #include "vtablefactory.hxx" #include +#include using namespace ::com::sun::star; namespace { -static inline typelib_TypeClass cpp2uno_call( - bridges::cpp_uno::shared::CppInterfaceProxy * pThis, - const typelib_TypeDescription * pMemberTD, - typelib_TypeDescriptionReference * pReturnTypeRef, // nullptr indicates void return - sal_Int32 nParams, - typelib_MethodParameter * pParams, - void ** pCallStack, - sal_Int64 * pRegisterReturn /* space for register return */) -{ - // pCallStack: ret, this, [complex return ptr], params - char * pCppCallStack = (char *)(pCallStack +2); - - // return type - typelib_TypeDescription * pReturnTD = nullptr; - if (pReturnTypeRef) - TYPELIB_DANGER_GET(&pReturnTD, pReturnTypeRef); - - void * pUnoReturn = nullptr; - void * pCppReturn = nullptr; // complex return ptr: if != nullptr && != pUnoReturn, reconversion need - - if (pReturnTD) - { - if (bridges::cpp_uno::shared::isSimpleType(pReturnTD)) - pUnoReturn = pRegisterReturn; - else - { - pCppReturn = *(void **)pCppCallStack; - pCppCallStack += sizeof(void *); - - pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType(pReturnTD) - ? alloca(pReturnTD->nSize) : pCppReturn); - } - } - - static_assert(sizeof(void *) == sizeof(sal_Int32), "### unexpected size!"); - - // parameters passed to the UNO function - void ** pUnoArgs = static_cast(alloca(4 * sizeof(void *) * nParams)); - - // parameters received from C++ - void ** pCppArgs = pUnoArgs + nParams; - - // indexes of values this have to be converted (interface conversion C++<=>UNO) - sal_Int32 * pTempIndexes = reinterpret_cast(pUnoArgs + (2 * nParams)); - - // type descriptions for reconversions - typelib_TypeDescription ** ppTempParamTD = - reinterpret_cast(pUnoArgs + (3 * nParams)); - - sal_Int32 nTempIndex = 0; - - for (sal_Int32 nPos = 0; nPos < nParams; ++nPos) - { - const typelib_MethodParameter & rParam = pParams[nPos]; - typelib_TypeDescription * pParamTD = nullptr; - TYPELIB_DANGER_GET(&pParamTD, rParam.pTypeRef); - - if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType(pParamTD)) - { - pCppArgs[nPos] = pCppCallStack; - pUnoArgs[nPos] = pCppCallStack; - switch (pParamTD->eTypeClass) - { - case typelib_TypeClass_HYPER: - case typelib_TypeClass_UNSIGNED_HYPER: - case typelib_TypeClass_DOUBLE: - pCppCallStack += sizeof(sal_Int32); // extra long - break; - default: - break; - } - // no longer needed - TYPELIB_DANGER_RELEASE(pParamTD); - } - else // ptr to complex value | ref - { - pCppArgs[nPos] = *(void **)pCppCallStack; - - if (!rParam.bIn) // is pure out - { - // UNO out is unconstructed mem - pUnoArgs[nPos] = alloca(pParamTD->nSize); - pTempIndexes[nTempIndex] = nPos; - // pParamTD will be released at reconversion - ppTempParamTD[nTempIndex++] = pParamTD; - } - // is in/inout - else if (bridges::cpp_uno::shared::relatesToInterfaceType(pParamTD)) - { - ::uno_copyAndConvertData( - pUnoArgs[nPos] = alloca(pParamTD->nSize), - *(void **)pCppCallStack, pParamTD, - pThis->getBridge()->getCpp2Uno()); - pTempIndexes[nTempIndex] = nPos; // has to be reconverted - // pParamTD will be released at reconversion - ppTempParamTD[nTempIndex++] = pParamTD; - } - else // direct way - { - pUnoArgs[nPos] = *(void **)pCppCallStack; - // no longer needed - TYPELIB_DANGER_RELEASE(pParamTD); - } - } - pCppCallStack += sizeof(sal_Int32); // standard parameter length - } - - // ExceptionHolder - uno_Any aUnoExc; // Any will be constructed by callee - uno_Any * pUnoExc = &aUnoExc; - - // invoke UNO dispatch call - (*pThis->getUnoI()->pDispatcher)( - pThis->getUnoI(), pMemberTD, pUnoReturn, pUnoArgs, &pUnoExc); - - // in case an exception occurred... - if (pUnoExc) - { - // destruct temporary in/inout params - while (nTempIndex--) - { - sal_Int32 nIndex = pTempIndexes[nTempIndex]; - - if (pParams[nIndex].bIn) // is in/inout => was constructed - ::uno_destructData(pUnoArgs[nIndex], ppTempParamTD[nTempIndex], nullptr); - TYPELIB_DANGER_RELEASE(ppTempParamTD[nTempIndex]); - } - if (pReturnTD) - TYPELIB_DANGER_RELEASE(pReturnTD); - - msvc_raiseException( - &aUnoExc, pThis->getBridge()->getUno2Cpp()); // has to destruct the any - - // is here for dummy - return typelib_TypeClass_VOID; - } - else // no exception occurred... - { - // temporary params - while (nTempIndex--) - { - sal_Int32 nIndex = pTempIndexes[nTempIndex]; - typelib_TypeDescription * pParamTD = ppTempParamTD[nTempIndex]; - - if (pParams[nIndex].bOut) // inout/out - { - // convert and assign - ::uno_destructData(pCppArgs[nIndex], pParamTD, uno::cpp_release); - ::uno_copyAndConvertData( - pCppArgs[nIndex], pUnoArgs[nIndex], pParamTD, - pThis->getBridge()->getUno2Cpp()); - } - // destroy temp UNO param - ::uno_destructData(pUnoArgs[nIndex], pParamTD, nullptr); - - TYPELIB_DANGER_RELEASE(pParamTD); - } - - // return - if (pCppReturn) // has complex return - { - if (pUnoReturn != pCppReturn) // needs reconversion - { - ::uno_copyAndConvertData( - pCppReturn, pUnoReturn, pReturnTD, - pThis->getBridge()->getUno2Cpp()); - // destroy temp UNO return - ::uno_destructData(pUnoReturn, pReturnTD, nullptr); - } - // complex return ptr is set to eax - *(void **)pRegisterReturn = pCppReturn; - } - - if (pReturnTD) - { - typelib_TypeClass eRet = pReturnTD->eTypeClass; - TYPELIB_DANGER_RELEASE(pReturnTD); - return eRet; - } - else - return typelib_TypeClass_VOID; - } -} - -static typelib_TypeClass __cdecl cpp_mediate( - void ** pCallStack, - sal_Int32 nFunctionIndex, - sal_Int32 nVtableOffset, - sal_Int64 * pRegisterReturn) // space for register return -{ - static_assert(sizeof(sal_Int32)==sizeof(void *), "### unexpected!"); - - // pCallStack: ret adr, this, [ret *], params - // pRegisterReturn is either the direct "return value", or is set to - // "ret *" and the real return value is constructed at that pointer. - - void* pThis = static_cast(pCallStack[1]) - nVtableOffset; - bridges::cpp_uno::shared::CppInterfaceProxy* pCppI - = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(pThis); - - typelib_InterfaceTypeDescription * pInterfaceTD = pCppI->getTypeDescr(); - - SAL_INFO("bridges", "cpp_vtable_call: pCallStack=[" - << std::hex << pCallStack[0] << "," << pCallStack[1] << "," - << pCallStack[2] << ",...], pThis=" << pThis << ", pCppI=" << pCppI - << std::dec << ", nFunctionIndex=" << nFunctionIndex - << ", nVtableOffset=" << nVtableOffset); - SAL_INFO("bridges", "name=" << OUString::unacquired(&pInterfaceTD->aBase.pTypeName)); - - if (nFunctionIndex >= pInterfaceTD->nMapFunctionIndexToMemberIndex) - { - OUString sError = "illegal " + OUString::unacquired(&pInterfaceTD->aBase.pTypeName) - + " vtable index " + OUString::number(nFunctionIndex) + "/" - + OUString::number(pInterfaceTD->nMapFunctionIndexToMemberIndex); - SAL_WARN("bridges", sError); - throw uno::RuntimeException(sError, reinterpret_cast(pThis)); - } - - // determine called method - sal_Int32 nMemberPos = pInterfaceTD->pMapFunctionIndexToMemberIndex[nFunctionIndex]; - assert(nMemberPos < pInterfaceTD->nAllMembers); - - uno::TypeDescription aMemberDescr(pInterfaceTD->ppAllMembers[nMemberPos]); - - SAL_INFO( "bridges", "Calling " << OUString::unacquired(&aMemberDescr.get()->pTypeName) ); - - typelib_TypeClass eRet = typelib_TypeClass_VOID; - switch (aMemberDescr.get()->eTypeClass) - { - case typelib_TypeClass_INTERFACE_ATTRIBUTE: - { - typelib_TypeDescriptionReference *pAttrTypeRef - = reinterpret_cast(aMemberDescr.get()) - ->pAttributeTypeRef; - - if (pInterfaceTD->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex) - { - // is GET method - eRet = cpp2uno_call(pCppI, aMemberDescr.get(), pAttrTypeRef, 0, nullptr, pCallStack, - pRegisterReturn); - } - else - { - // is SET method - typelib_MethodParameter aParam; - aParam.pTypeRef = pAttrTypeRef; - aParam.bIn = true; - aParam.bOut = false; - - eRet = cpp2uno_call(pCppI, aMemberDescr.get(), nullptr, 1, &aParam, pCallStack, - pRegisterReturn); - } - break; - } - case typelib_TypeClass_INTERFACE_METHOD: - { - // is METHOD - switch (nFunctionIndex) - { - // standard XInterface vtable calls - case 1: // acquire() - pCppI->acquireProxy(); // non virtual call! - eRet = typelib_TypeClass_VOID; - break; - case 2: // release() - pCppI->releaseProxy(); // non virtual call! - eRet = typelib_TypeClass_VOID; - break; - case 0: // queryInterface() opt - { - typelib_TypeDescription* pQueryTD = nullptr; - TYPELIB_DANGER_GET(&pQueryTD, - static_cast(pCallStack[3])->getTypeLibType()); - if (pQueryTD) - { - uno::XInterface* pInterface = nullptr; - - pCppI->getBridge()->getCppEnv()->getRegisteredInterface( - pCppI->getBridge()->getCppEnv(), reinterpret_cast(&pInterface), - pCppI->getOid().pData, - reinterpret_cast(pQueryTD)); - - if (pInterface) - { - ::uno_any_construct(static_cast(pCallStack[2]), &pInterface, - pQueryTD, uno::cpp_acquire); - pInterface->release(); - TYPELIB_DANGER_RELEASE(pQueryTD); - - *(void **)pRegisterReturn = pCallStack[2]; - eRet = typelib_TypeClass_ANY; - break; - } - TYPELIB_DANGER_RELEASE(pQueryTD); - } - [[fallthrough]]; - } - default: // perform queryInterface() - { - typelib_InterfaceMethodTypeDescription* pMethodTD - = reinterpret_cast( - aMemberDescr.get()); - - eRet = cpp2uno_call(pCppI, aMemberDescr.get(), pMethodTD->pReturnTypeRef, - pMethodTD->nParams, pMethodTD->pParams, pCallStack, - pRegisterReturn); - } - } - break; - } - default: - throw uno::RuntimeException("no member description found!", - reinterpret_cast(pThis)); - } - - return eRet; -} - /** * is called on incoming vtable calls * (called by asm snippets) diff --git a/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx b/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx index 6ed58ed4c9e6..34ba34fb2856 100644 --- a/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx +++ b/bridges/source/cpp_uno/msvc_win32_x86-64/cpp2uno.cxx @@ -31,313 +31,16 @@ #include #include "call.hxx" +#include #include using namespace ::com::sun::star; -static typelib_TypeClass cpp2uno_call( - bridges::cpp_uno::shared::CppInterfaceProxy * pThis, - const typelib_TypeDescription * pMemberTD, - typelib_TypeDescriptionReference * pReturnTypeRef, // nullptr indicates void return - sal_Int32 nParams, - typelib_MethodParameter * pParams, - void ** pCallStack) -{ - // return type - typelib_TypeDescription * pReturnTD = nullptr; - if (pReturnTypeRef) - TYPELIB_DANGER_GET(&pReturnTD, pReturnTypeRef); - - int nFirstRealParam = 3; // Index into pCallStack, past return - // value, return address and 'this' - // pointer. - - void * pUnoReturn = nullptr; - void * pCppReturn = nullptr; // complex return ptr: if != nullptr && != pUnoReturn, reconversion need - - if (pReturnTD) - { - if (bridges::cpp_uno::shared::isSimpleType(pReturnTD)) - pUnoReturn = pCallStack; - else - { - pCppReturn = pCallStack[nFirstRealParam++]; - pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType(pReturnTD) - ? alloca(pReturnTD->nSize) : pCppReturn); - } - } - - void ** pCppIncomingParams = pCallStack + nFirstRealParam; - - // Unlike this method for other archs, prefer clarity to - // micro-optimization, and allocate these array separately - - // parameters passed to the UNO function - void ** pUnoArgs = static_cast(alloca(sizeof(void *) * nParams)); - - // parameters received from C++ - void ** pCppArgs = static_cast(alloca(sizeof(void *) * nParams)); - - // indexes of values this have to be converted (interface conversion C++<=>UNO) - sal_Int32 * pTempIndexes = static_cast(alloca(sizeof(sal_Int32) * nParams)); - - // type descriptions for reconversions - typelib_TypeDescription ** ppTempParamTD = - static_cast(alloca(sizeof(void *) * nParams)); - - sal_Int32 nTempIndex = 0; - - for (sal_Int32 nPos = 0; nPos < nParams; ++nPos) - { - const typelib_MethodParameter & rParam = pParams[nPos]; - typelib_TypeDescription * pParamTD = nullptr; - TYPELIB_DANGER_GET(&pParamTD, rParam.pTypeRef); - - if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType(pParamTD)) - { - pCppArgs[nPos] = pUnoArgs[nPos] = pCppIncomingParams++; - TYPELIB_DANGER_RELEASE(pParamTD); - } - else // ptr to complex value | ref - { - void * pCppCallStack; - - pCppArgs[nPos] = pCppCallStack = *pCppIncomingParams++; - - if (!rParam.bIn) // is pure out - { - // UNO out is unconstructed mem - pUnoArgs[nPos] = alloca(pParamTD->nSize); - pTempIndexes[nTempIndex] = nPos; - // pParamTD will be released at reconversion - ppTempParamTD[nTempIndex++] = pParamTD; - } - else if (bridges::cpp_uno::shared::relatesToInterfaceType(pParamTD)) - { - ::uno_copyAndConvertData( - pUnoArgs[nPos] = alloca(pParamTD->nSize), - pCppCallStack, pParamTD, - pThis->getBridge()->getCpp2Uno()); - pTempIndexes[nTempIndex] = nPos; // has to be reconverted - // pParamTD will be released at reconversion - ppTempParamTD[nTempIndex++] = pParamTD; - } - else // direct way - { - pUnoArgs[nPos] = pCppCallStack; - // no longer needed - TYPELIB_DANGER_RELEASE(pParamTD); - } - } - } - - // ExceptionHolder - uno_Any aUnoExc; // Any will be constructed by callee - uno_Any * pUnoExc = &aUnoExc; - - // invoke UNO dispatch call - (*pThis->getUnoI()->pDispatcher)( - pThis->getUnoI(), pMemberTD, pUnoReturn, pUnoArgs, &pUnoExc); - - // in case an exception occurred... - if (pUnoExc) - { - // destruct temporary in/inout params - while (nTempIndex--) - { - sal_Int32 nIndex = pTempIndexes[nTempIndex]; - - if (pParams[nIndex].bIn) // is in/inout => was constructed - ::uno_destructData(pUnoArgs[nIndex], ppTempParamTD[nTempIndex], nullptr); - TYPELIB_DANGER_RELEASE(ppTempParamTD[nTempIndex]); - } - if (pReturnTD) - TYPELIB_DANGER_RELEASE(pReturnTD); - - msvc_raiseException( - &aUnoExc, pThis->getBridge()->getUno2Cpp()); // has to destruct the any - - // is here for dummy - return typelib_TypeClass_VOID; - } - else // no exception occurred... - { - // temporary params - while (nTempIndex--) - { - sal_Int32 nIndex = pTempIndexes[nTempIndex]; - typelib_TypeDescription * pParamTD = ppTempParamTD[nTempIndex]; - - if (pParams[nIndex].bOut) // inout/out - { - // convert and assign - ::uno_destructData(pCppArgs[nIndex], pParamTD, uno::cpp_release); - ::uno_copyAndConvertData( - pCppArgs[nIndex], pUnoArgs[nIndex], pParamTD, - pThis->getBridge()->getUno2Cpp()); - } - // destroy temp UNO param - ::uno_destructData(pUnoArgs[nIndex], pParamTD, nullptr); - - TYPELIB_DANGER_RELEASE(pParamTD); - } - - // return - if (pCppReturn) // has complex return - { - if (pUnoReturn != pCppReturn) // needs reconversion - { - ::uno_copyAndConvertData( - pCppReturn, pUnoReturn, pReturnTD, - pThis->getBridge()->getUno2Cpp()); - // destroy temp UNO return - ::uno_destructData(pUnoReturn, pReturnTD, nullptr); - } - // complex return ptr is set to eax - pCallStack[0] = pCppReturn; - } - - if (pReturnTD) - { - typelib_TypeClass eRet = pReturnTD->eTypeClass; - TYPELIB_DANGER_RELEASE(pReturnTD); - return eRet; - } - else - return typelib_TypeClass_VOID; - } -} - -extern "C" typelib_TypeClass cpp_vtable_call( - sal_Int64 nOffsetAndIndex, - void ** pCallStack) +extern "C" typelib_TypeClass cpp_vtable_call(sal_Int64 nOffsetAndIndex, void ** pCallStack) { sal_Int32 nFunctionIndex = (nOffsetAndIndex & 0xFFFFFFFF); sal_Int32 nVtableOffset = ((nOffsetAndIndex >> 32) & 0xFFFFFFFF); - - // pCallStack: ret value, ret adr, this, [ret *], params - // pCallStack[0] is either the direct "return value", or is set to "ret *" and - // the real return value is constructed at that memory. - - void* pThis = static_cast(pCallStack[2]) - nVtableOffset; - bridges::cpp_uno::shared::CppInterfaceProxy* pCppI - = bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(pThis); - - typelib_InterfaceTypeDescription * pInterfaceTD = pCppI->getTypeDescr(); - - SAL_INFO("bridges", "cpp_vtable_call: pCallStack=[" - << std::hex << pCallStack[0] << "," << pCallStack[1] << "," - << pCallStack[2] << ",...], pThis=" << pThis << ", pCppI=" << pCppI - << std::dec << ", nFunctionIndex=" << nFunctionIndex - << ", nVtableOffset=" << nVtableOffset); - SAL_INFO("bridges", "name=" << OUString::unacquired(&pInterfaceTD->aBase.pTypeName)); - - if (nFunctionIndex >= pInterfaceTD->nMapFunctionIndexToMemberIndex) - { - OUString sError = "illegal " + OUString::unacquired(&pInterfaceTD->aBase.pTypeName) - + " vtable index " + OUString::number(nFunctionIndex) + "/" - + OUString::number(pInterfaceTD->nMapFunctionIndexToMemberIndex); - SAL_WARN("bridges", sError); - throw uno::RuntimeException(sError, reinterpret_cast(pThis)); - } - - // determine called method - sal_Int32 nMemberPos = pInterfaceTD->pMapFunctionIndexToMemberIndex[nFunctionIndex]; - assert(nMemberPos < pInterfaceTD->nAllMembers); - - uno::TypeDescription aMemberDescr(pInterfaceTD->ppAllMembers[nMemberPos]); - - SAL_INFO( "bridges", "Calling " << OUString::unacquired(&aMemberDescr.get()->pTypeName) ); - - typelib_TypeClass eRet = typelib_TypeClass_VOID; - switch (aMemberDescr.get()->eTypeClass) - { - case typelib_TypeClass_INTERFACE_ATTRIBUTE: - { - typelib_TypeDescriptionReference *pAttrTypeRef - = reinterpret_cast(aMemberDescr.get()) - ->pAttributeTypeRef; - - if (pInterfaceTD->pMapMemberIndexToFunctionIndex[nMemberPos] == nFunctionIndex) - { - // is GET method - eRet = cpp2uno_call(pCppI, aMemberDescr.get(), pAttrTypeRef, 0, nullptr, pCallStack); - } - else - { - // is SET method - typelib_MethodParameter aParam; - aParam.pTypeRef = pAttrTypeRef; - aParam.bIn = true; - aParam.bOut = false; - - eRet = cpp2uno_call(pCppI, aMemberDescr.get(), nullptr, 1, &aParam, pCallStack); - } - break; - } - case typelib_TypeClass_INTERFACE_METHOD: - { - // is METHOD - switch (nFunctionIndex) - { - case 1: // acquire() - pCppI->acquireProxy(); // non virtual call! - eRet = typelib_TypeClass_VOID; - break; - case 2: // release() - pCppI->releaseProxy(); // non virtual call! - eRet = typelib_TypeClass_VOID; - break; - case 0: // queryInterface() opt - { - typelib_TypeDescription* pQueryTD = nullptr; - - TYPELIB_DANGER_GET(&pQueryTD, - static_cast(pCallStack[4])->getTypeLibType()); - - if (pQueryTD) - { - uno::XInterface* pInterface = nullptr; - - pCppI->getBridge()->getCppEnv()->getRegisteredInterface( - pCppI->getBridge()->getCppEnv(), reinterpret_cast(&pInterface), - pCppI->getOid().pData, - reinterpret_cast(pQueryTD)); - - if (pInterface) - { - // pCallStack[3] = hidden return value pointer - ::uno_any_construct(static_cast(pCallStack[3]), &pInterface, - pQueryTD, uno::cpp_acquire); - pInterface->release(); - TYPELIB_DANGER_RELEASE(pQueryTD); - - pCallStack[0] = pCallStack[3]; - eRet = typelib_TypeClass_ANY; - break; - } - TYPELIB_DANGER_RELEASE(pQueryTD); - } - [[fallthrough]]; - } - default: // perform queryInterface() - { - typelib_InterfaceMethodTypeDescription* pMethodTD - = reinterpret_cast( - aMemberDescr.get()); - - eRet = cpp2uno_call(pCppI, aMemberDescr.get(), pMethodTD->pReturnTypeRef, - pMethodTD->nParams, pMethodTD->pParams, pCallStack); - } - } - break; - } - default: - throw uno::RuntimeException("No member description found!", - reinterpret_cast(pThis)); - } - - return eRet; + return cpp_mediate(pCallStack, nFunctionIndex, nVtableOffset, nullptr); } int const codeSnippetSize = 48; -- cgit