[Libreoffice-commits] core.git: bridges/Library_cpp_uno.mk bridges/source

Tor Lillqvist tml at iki.fi
Sun Dec 8 04:17:07 PST 2013


 bridges/Library_cpp_uno.mk                            |    2 
 bridges/source/cpp_uno/gcc3_ios_arm/cpp2uno-arm.cxx   |    2 
 bridges/source/cpp_uno/gcc3_ios_arm/cpp2uno-arm64.cxx |  566 +++++++++++++++
 bridges/source/cpp_uno/gcc3_ios_arm/uno2cpp-arm.cxx   |   19 
 bridges/source/cpp_uno/gcc3_ios_arm/uno2cpp-arm64.cxx |  640 ++++++++++++++++++
 5 files changed, 1209 insertions(+), 20 deletions(-)

New commits:
commit 72bbd83c03284797ffae2c4ca28abb750b75da72
Author: Tor Lillqvist <tml at iki.fi>
Date:   Sun Nov 17 11:44:23 2013 +0200

    Intermediate work in progress commit on the arm64 C++/UNO bridge
    
    Note that the arm64 code is not even close to "working" yet.
    
    Change-Id: I261d09f7e797cded26396ed0d4b8b3021f712ebf

diff --git a/bridges/Library_cpp_uno.mk b/bridges/Library_cpp_uno.mk
index 79d2119..1dc13f4 100644
--- a/bridges/Library_cpp_uno.mk
+++ b/bridges/Library_cpp_uno.mk
@@ -21,7 +21,7 @@ ifeq ($(OS),IOS)
 $(eval $(call gb_Library_use_sdk_api,gcc3_uno))
 bridges_SELECTED_BRIDGE := gcc3_ios_arm
 bridge_asm_objects := helper
-bridge_exception_objects := cpp2uno cpp2uno-arm cpp2uno-i386 except uno2cpp uno2cpp-arm uno2cpp-i386
+bridge_exception_objects := cpp2uno cpp2uno-arm cpp2uno-arm64 cpp2uno-i386 except uno2cpp uno2cpp-arm uno2cpp-arm64 uno2cpp-i386
 $(eval $(call gb_Library_use_custom_headers,gcc3_uno,\
 	bridges/source/cpp_uno/gcc3_ios_arm \
 ))
diff --git a/bridges/source/cpp_uno/gcc3_ios_arm/cpp2uno-arm.cxx b/bridges/source/cpp_uno/gcc3_ios_arm/cpp2uno-arm.cxx
index 6abdad9..b873dac 100644
--- a/bridges/source/cpp_uno/gcc3_ios_arm/cpp2uno-arm.cxx
+++ b/bridges/source/cpp_uno/gcc3_ios_arm/cpp2uno-arm.cxx
@@ -17,7 +17,7 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
-#if defined(__arm) || defined(__arm64)
+#ifdef __arm
 
 // For iOS devices (ARM). Basically a copy of
 // ../gcc3_linux_arm/cpp2uno.cxx with some cleanups and necessary
diff --git a/bridges/source/cpp_uno/gcc3_ios_arm/cpp2uno-arm64.cxx b/bridges/source/cpp_uno/gcc3_ios_arm/cpp2uno-arm64.cxx
new file mode 100644
index 0000000..54441b8
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_ios_arm/cpp2uno-arm64.cxx
@@ -0,0 +1,566 @@
+/* -*- 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 .
+ */
+
+#ifdef __arm64
+
+// For iOS devices (64-bit ARM). Originally a copy of
+// ../gcc3_linux_arm/cpp2uno.cxx with some cleanups and necessary
+// changes: No dynamic code generation as that is prohibited for apps
+// in the App Store. Instead we use a set of pre-generated snippets.
+
+// No attempts at factoring out the large amounts of more or less
+// common code in this, cpp2uno-arm.cxx and cpp2uno-i386.cxx have been
+// done. Which is sad. But then the whole bridges/source/cpp_uno is
+// full of copy/paste. So I continue in that tradition...
+
+#include <com/sun/star/uno/RuntimeException.hpp>
+#include <uno/data.h>
+#include <typelib/typedescription.hxx>
+
+#include "bridges/cpp_uno/shared/bridge.hxx"
+#include "bridges/cpp_uno/shared/cppinterfaceproxy.hxx"
+#include "bridges/cpp_uno/shared/types.hxx"
+#include "bridges/cpp_uno/shared/vtablefactory.hxx"
+
+#include "share.hxx"
+
+extern "C" {
+    extern int nFunIndexes, nVtableOffsets;
+    extern int codeSnippets[];
+}
+
+using namespace ::com::sun::star::uno;
+
+namespace
+{
+
+    static typelib_TypeClass cpp2uno_call(
+        bridges::cpp_uno::shared::CppInterfaceProxy* pThis,
+        const typelib_TypeDescription * pMemberTypeDescr,
+        typelib_TypeDescriptionReference * pReturnTypeRef,
+        sal_Int32 nParams, typelib_MethodParameter * pParams,
+        void ** pCallStack,
+        sal_Int64 * pRegisterReturn /* space for register return */ )
+    {
+        // pCallStack: ret, [return ptr], this, params
+        char * pTopStack = (char *)(pCallStack + 0);
+        char * pCppStack = pTopStack;
+
+#ifdef __ARM_PCS_VFP
+        int dc = 0;
+        char * pFloatArgs = (char *)(pCppStack - 64);
+#endif
+        // return
+        typelib_TypeDescription * pReturnTypeDescr = 0;
+        if (pReturnTypeRef)
+            TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
+
+        void * pUnoReturn = 0;
+        // complex return ptr: if != 0 && != pUnoReturn, reconversion need
+        void * pCppReturn = 0;
+
+        if (pReturnTypeDescr)
+        {
+            if (!arm::return_in_hidden_param(pReturnTypeRef))
+                pUnoReturn = pRegisterReturn; // direct way for simple types
+            else // complex return via ptr (pCppReturn)
+            {
+                pCppReturn = *(void **)pCppStack;
+                pCppStack += 16;
+
+                pUnoReturn = (bridges::cpp_uno::shared::relatesToInterfaceType(
+                    pReturnTypeDescr )
+                        ? alloca( pReturnTypeDescr->nSize )
+                        : pCppReturn); // direct way
+            }
+        }
+        // pop this
+        pCppStack += sizeof( void* );
+
+        // Parameters
+        void ** pUnoArgs = (void **)alloca( sizeof(void *) * nParams );
+        void ** pCppArgs = (void **)alloca( sizeof(void *) * nParams );
+
+        // Indices of values this have to be converted (interface conversion
+        // cpp<=>uno)
+        sal_Int32 * pTempIndices = (sal_Int32 *)alloca( sizeof(sal_Int32) * nParams);
+
+        // Type descriptions for reconversions
+        typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)alloca( sizeof(typelib_TypeDescription *) * nParams);
+
+        sal_Int32 nTempIndices   = 0;
+
+        for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
+        {
+            const typelib_MethodParameter & rParam = pParams[nPos];
+            typelib_TypeDescription * pParamTypeDescr = 0;
+            TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
+
+            if (!rParam.bOut &&
+                bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
+            {
+#ifdef __ARM_EABI__
+                switch (pParamTypeDescr->eTypeClass)
+                {
+                    case typelib_TypeClass_HYPER:
+                    case typelib_TypeClass_UNSIGNED_HYPER:
+#ifndef __ARM_PCS_VFP
+                    case typelib_TypeClass_DOUBLE:
+#endif
+                        if ((pCppStack - pTopStack) % 8) pCppStack+=sizeof(sal_Int32); //align to 8
+                        break;
+                    default:
+                        break;
+                }
+#endif
+
+// For armhf we get the floating point arguments from a different area of the stack
+#ifdef __ARM_PCS_VFP
+                if (pParamTypeDescr->eTypeClass == typelib_TypeClass_FLOAT)
+                {
+                    pCppArgs[nPos] =  pUnoArgs[nPos] = pFloatArgs;
+                    pFloatArgs += sizeof(float);
+                } else
+                if (pParamTypeDescr->eTypeClass == typelib_TypeClass_DOUBLE)
+                {
+                    if ((pFloatArgs - pTopStack) % 8) pFloatArgs+=sizeof(float); //align to 8
+                    pCppArgs[nPos] = pUnoArgs[nPos] = pFloatArgs;
+                    pFloatArgs += sizeof(double);
+                    if (++dc == arm::MAX_FPR_REGS) {
+                        if (pCppStack - pTopStack < 16)
+                            pCppStack = pTopStack + 16;
+                        pFloatArgs = pCppStack;
+                    }
+                } else
+#endif
+                    pCppArgs[nPos] = pUnoArgs[nPos] = pCppStack;
+
+                switch (pParamTypeDescr->eTypeClass)
+                {
+                    case typelib_TypeClass_HYPER:
+                    case typelib_TypeClass_UNSIGNED_HYPER:
+#ifndef __ARM_PCS_VFP
+                    case typelib_TypeClass_DOUBLE:
+#endif
+                        pCppStack += sizeof(sal_Int32); // extra long
+                        break;
+                    default:
+                        break;
+                }
+                // no longer needed
+                TYPELIB_DANGER_RELEASE( pParamTypeDescr );
+            }
+            else // ptr to complex value | ref
+            {
+                pCppArgs[nPos] = *(void **)pCppStack;
+
+                if (! rParam.bIn) // is pure out
+                {
+                    // uno out is unconstructed mem!
+                    pUnoArgs[nPos] = alloca( pParamTypeDescr->nSize );
+                    pTempIndices[nTempIndices] = nPos;
+                    // will be released at reconversion
+                    ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
+                }
+                // is in/inout
+                else if (bridges::cpp_uno::shared::relatesToInterfaceType(
+                    pParamTypeDescr ))
+                {
+                    uno_copyAndConvertData( pUnoArgs[nPos] =
+                        alloca( pParamTypeDescr->nSize ),
+                        *(void **)pCppStack, pParamTypeDescr,
+                        pThis->getBridge()->getCpp2Uno() );
+                    pTempIndices[nTempIndices] = nPos; // has to be reconverted
+                    // will be released at reconversion
+                    ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
+                }
+                else // direct way
+                {
+                    pUnoArgs[nPos] = *(void **)pCppStack;
+                    // no longer needed
+                    TYPELIB_DANGER_RELEASE( pParamTypeDescr );
+                }
+            }
+#ifdef __ARM_PCS_VFP
+            // use the stack for output parameters or non floating point values
+                if (rParam.bOut ||
+                        ((pParamTypeDescr->eTypeClass != typelib_TypeClass_DOUBLE)
+                         && (pParamTypeDescr->eTypeClass != typelib_TypeClass_FLOAT))
+                    )
+#endif
+            pCppStack += 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(), pMemberTypeDescr, pUnoReturn, pUnoArgs, &pUnoExc );
+
+        // in case an exception occurred...
+        if (pUnoExc)
+        {
+            // destruct temporary in/inout params
+            for ( ; nTempIndices--; )
+            {
+                sal_Int32 nIndex = pTempIndices[nTempIndices];
+
+                if (pParams[nIndex].bIn) // is in/inout => was constructed
+                    uno_destructData( pUnoArgs[nIndex],
+                        ppTempParamTypeDescr[nTempIndices], 0 );
+                TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndices] );
+            }
+            if (pReturnTypeDescr)
+                TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
+
+            CPPU_CURRENT_NAMESPACE::raiseException( &aUnoExc,
+                pThis->getBridge()->getUno2Cpp() ); // has to destruct the any
+            // is here for dummy
+            return typelib_TypeClass_VOID;
+        }
+        else // else no exception occurred...
+        {
+            // temporary params
+            for ( ; nTempIndices--; )
+            {
+                sal_Int32 nIndex = pTempIndices[nTempIndices];
+                typelib_TypeDescription * pParamTypeDescr =
+                    ppTempParamTypeDescr[nTempIndices];
+
+                if (pParams[nIndex].bOut) // inout/out
+                {
+                    // convert and assign
+                    uno_destructData( pCppArgs[nIndex], pParamTypeDescr,
+                        cpp_release );
+                    uno_copyAndConvertData( pCppArgs[nIndex], pUnoArgs[nIndex],
+                        pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
+                }
+                // destroy temp uno param
+                uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 );
+
+                TYPELIB_DANGER_RELEASE( pParamTypeDescr );
+            }
+            // return
+            if (pCppReturn) // has complex return
+            {
+                if (pUnoReturn != pCppReturn) // needs reconversion
+                {
+                    uno_copyAndConvertData( pCppReturn, pUnoReturn,
+                        pReturnTypeDescr, pThis->getBridge()->getUno2Cpp() );
+                    // destroy temp uno return
+                    uno_destructData( pUnoReturn, pReturnTypeDescr, 0 );
+                }
+                // complex return ptr is set to eax
+                *(void **)pRegisterReturn = pCppReturn;
+            }
+            if (pReturnTypeDescr)
+            {
+                typelib_TypeClass eRet =
+                    (typelib_TypeClass)pReturnTypeDescr->eTypeClass;
+                TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
+                return eRet;
+            }
+            else
+                return typelib_TypeClass_VOID;
+        }
+    }
+
+
+    //=====================================================================
+    static typelib_TypeClass cpp_mediate(
+        sal_Int32 nFunctionIndex, sal_Int32 nVtableOffset,
+        void ** pCallStack,
+        sal_Int64 * pRegisterReturn /* space for register return */ )
+    {
+        OSL_ENSURE( sizeof(sal_Int32)==sizeof(void *), "### unexpected!" );
+
+        // pCallStack: [ret *], this, params
+        // _this_ ptr is patched cppu_XInterfaceProxy object
+        void *pThis;
+        if( nFunctionIndex & 0x80000000 )
+        {
+            nFunctionIndex &= 0x7fffffff;
+            pThis = pCallStack[1];
+        }
+        else
+        {
+            pThis = pCallStack[0];
+        }
+
+        pThis = static_cast< char * >(pThis) - nVtableOffset;
+        bridges::cpp_uno::shared::CppInterfaceProxy * pCppI =
+            bridges::cpp_uno::shared::CppInterfaceProxy::castInterfaceToProxy(
+                pThis);
+
+        typelib_InterfaceTypeDescription * pTypeDescr = pCppI->getTypeDescr();
+
+        OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex,
+            "### illegal vtable index!" );
+        if (nFunctionIndex >= pTypeDescr->nMapFunctionIndexToMemberIndex)
+        {
+            throw RuntimeException( "illegal vtable index!", (XInterface *)pCppI );
+        }
+
+        // determine called method
+        OSL_ENSURE( nFunctionIndex < pTypeDescr->nMapFunctionIndexToMemberIndex,
+            "### illegal vtable index!" );
+        sal_Int32 nMemberPos =
+            pTypeDescr->pMapFunctionIndexToMemberIndex[nFunctionIndex];
+        OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers,
+            "### illegal member index!" );
+
+        TypeDescription aMemberDescr( pTypeDescr->ppAllMembers[nMemberPos] );
+
+        typelib_TypeClass eRet;
+        switch (aMemberDescr.get()->eTypeClass)
+        {
+        case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+        {
+            if (pTypeDescr->pMapMemberIndexToFunctionIndex[nMemberPos] ==
+                nFunctionIndex)
+            {
+                // is GET method
+                eRet = cpp2uno_call(
+                    pCppI, aMemberDescr.get(),
+                    ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef,
+                    0, 0, // no params
+                    pCallStack, pRegisterReturn );
+            }
+            else
+            {
+                // is SET method
+                typelib_MethodParameter aParam;
+                aParam.pTypeRef =
+                    ((typelib_InterfaceAttributeTypeDescription *)aMemberDescr.get())->pAttributeTypeRef;
+                aParam.bIn      = sal_True;
+                aParam.bOut     = sal_False;
+
+                eRet = cpp2uno_call(
+                    pCppI, aMemberDescr.get(),
+                    0, // indicates void return
+                    1, &aParam,
+                    pCallStack, pRegisterReturn );
+            }
+            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 * pTD = 0;
+                TYPELIB_DANGER_GET(&pTD,
+                    reinterpret_cast<Type *>(pCallStack[2])->getTypeLibType());
+                if (pTD)
+                {
+                    XInterface * pInterface = 0;
+                    (*pCppI->getBridge()->getCppEnv()->getRegisteredInterface)(
+                        pCppI->getBridge()->getCppEnv(),
+                        (void **)&pInterface, pCppI->getOid().pData,
+                        (typelib_InterfaceTypeDescription *)pTD );
+
+                    if (pInterface)
+                    {
+                        ::uno_any_construct(
+                            reinterpret_cast< uno_Any * >( pCallStack[0] ),
+                            &pInterface, pTD, cpp_acquire );
+                        pInterface->release();
+                        TYPELIB_DANGER_RELEASE( pTD );
+                        *(void **)pRegisterReturn = pCallStack[0];
+                        eRet = typelib_TypeClass_ANY;
+                        break;
+                    }
+                    TYPELIB_DANGER_RELEASE( pTD );
+                }
+            } // else perform queryInterface()
+            default:
+                eRet = cpp2uno_call(
+                    pCppI, aMemberDescr.get(),
+                    ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pReturnTypeRef,
+                    ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->nParams,
+                    ((typelib_InterfaceMethodTypeDescription *)aMemberDescr.get())->pParams,
+                    pCallStack, pRegisterReturn );
+            }
+            break;
+        }
+        default:
+        {
+            throw RuntimeException( "no member description found!", (XInterface *)pCppI );
+        }
+        }
+
+        return eRet;
+    }
+}
+
+//=======================================================================
+/**
+ * is called on incoming vtable calls
+ * (called by asm snippets)
+ */
+
+extern "C" sal_Int64 cpp_vtable_call( long *pFunctionAndOffset,
+    void **pCallStack )
+{
+    sal_Int64 nRegReturn;
+    typelib_TypeClass aType = cpp_mediate( pFunctionAndOffset[0], pFunctionAndOffset[1], pCallStack,
+        &nRegReturn );
+
+    switch( aType )
+    {
+        case typelib_TypeClass_BOOLEAN:
+        case typelib_TypeClass_BYTE:
+            nRegReturn = (unsigned long)(*(unsigned char *)&nRegReturn);
+            break;
+        case typelib_TypeClass_CHAR:
+        case typelib_TypeClass_UNSIGNED_SHORT:
+        case typelib_TypeClass_SHORT:
+            nRegReturn = (unsigned long)(*(unsigned short *)&nRegReturn);
+            break;
+        case typelib_TypeClass_ENUM:
+        case typelib_TypeClass_UNSIGNED_LONG:
+        case typelib_TypeClass_LONG:
+            nRegReturn = (unsigned long)(*(unsigned int *)&nRegReturn);
+            break;
+        case typelib_TypeClass_VOID:
+        default:
+            break;
+    }
+
+    return nRegReturn;
+}
+
+namespace
+{
+    unsigned char *codeSnippet(sal_Int32 functionIndex,
+        sal_Int32 vtableOffset, bool bHasHiddenParam)
+    {
+        assert(functionIndex < nFunIndexes);
+        if (!(functionIndex < nFunIndexes))
+            return NULL;
+
+        assert(vtableOffset < nVtableOffsets);
+        if (!(vtableOffset < nVtableOffsets))
+            return NULL;
+
+        // The codeSnippets table is indexed by functionIndex,
+        // vtableOffset, and the has-hidden-param flag
+
+        int index = functionIndex*nVtableOffsets*2 + vtableOffset*2 + bHasHiddenParam;
+        unsigned char *result = ((unsigned char *) &codeSnippets) + codeSnippets[index];
+
+        SAL_INFO( "bridges.ios",
+                  "codeSnippet: [" <<
+                  functionIndex << "," << vtableOffset << "," << bHasHiddenParam << "]=" <<
+                  (void *) result);
+
+        return result;
+    }
+}
+
+struct bridges::cpp_uno::shared::VtableFactory::Slot { void * fn; };
+
+bridges::cpp_uno::shared::VtableFactory::Slot *
+bridges::cpp_uno::shared::VtableFactory::mapBlockToVtable(void * block)
+{
+    return static_cast< Slot * >(block) + 2;
+}
+
+sal_Size bridges::cpp_uno::shared::VtableFactory::getBlockSize(
+    sal_Int32 slotCount)
+{
+    return (slotCount + 2) * sizeof (Slot);
+}
+
+bridges::cpp_uno::shared::VtableFactory::Slot *
+bridges::cpp_uno::shared::VtableFactory::initializeBlock(
+    void * block, sal_Int32 slotCount)
+{
+    Slot * slots = mapBlockToVtable(block);
+    slots[-2].fn = 0;
+    slots[-1].fn = 0;
+    return slots + slotCount;
+}
+
+unsigned char * bridges::cpp_uno::shared::VtableFactory::addLocalFunctions(
+    Slot ** slots, unsigned char * code,
+    typelib_InterfaceTypeDescription const * type, sal_Int32 functionOffset,
+    sal_Int32 functionCount, sal_Int32 vtableOffset)
+{
+    (*slots) -= functionCount;
+    Slot * s = *slots;
+    for (sal_Int32 i = 0; i < type->nMembers; ++i)
+    {
+        typelib_TypeDescription * member = 0;
+        TYPELIB_DANGER_GET(&member, type->ppMembers[i]);
+        OSL_ASSERT(member != 0);
+        switch (member->eTypeClass)
+        {
+            case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+            {
+                typelib_InterfaceAttributeTypeDescription *pAttrTD =
+                    reinterpret_cast<typelib_InterfaceAttributeTypeDescription *>( member );
+
+                // Getter:
+                (s++)->fn = codeSnippet(
+                    functionOffset++, vtableOffset,
+                    arm::return_in_hidden_param( pAttrTD->pAttributeTypeRef ));
+
+                // Setter:
+                if (!pAttrTD->bReadOnly)
+                {
+                    (s++)->fn = codeSnippet(
+                        functionOffset++, vtableOffset, false);
+                }
+                break;
+            }
+            case typelib_TypeClass_INTERFACE_METHOD:
+            {
+                typelib_InterfaceMethodTypeDescription *pMethodTD =
+                    reinterpret_cast<
+                        typelib_InterfaceMethodTypeDescription * >(member);
+
+                (s++)->fn = codeSnippet(functionOffset++, vtableOffset,
+                    arm::return_in_hidden_param(pMethodTD->pReturnTypeRef));
+                break;
+            }
+        default:
+            OSL_ASSERT(false);
+            break;
+        }
+        TYPELIB_DANGER_RELEASE(member);
+    }
+    return code;
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/bridges/source/cpp_uno/gcc3_ios_arm/uno2cpp-arm.cxx b/bridges/source/cpp_uno/gcc3_ios_arm/uno2cpp-arm.cxx
index 8467772..5943068 100644
--- a/bridges/source/cpp_uno/gcc3_ios_arm/uno2cpp-arm.cxx
+++ b/bridges/source/cpp_uno/gcc3_ios_arm/uno2cpp-arm.cxx
@@ -17,7 +17,7 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
-#if defined(__arm) || defined(__arm64)
+#ifdef __arm
 
 // For iOS devices (ARM). Basically a copy of
 // ../gcc3_linux_arm/cpp2uno.cxx with some cleanups and necessary
@@ -184,8 +184,6 @@ void callVirtualMethod(
     sal_uInt32 nGPR,
     double *pFPR)
 {
-#ifdef __arm
-
     // never called
     if (! pThis)
         CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything("xxx"); // address something
@@ -236,21 +234,6 @@ void callVirtualMethod(
         : "r0", "r1", "r2", "r3", "r4", "r5");
 
     MapReturn(r0, r1, pReturnType, (sal_uInt32*)pRegisterReturn);
-
-#else
-    abort(); // arm64 code not yet implemented
-
-    (void) pThis;
-    (void) nVtableIndex;
-    (void) pRegisterReturn;
-    (void) pReturnType;
-    (void) pStack;
-    (void) nStack;
-    (void) pGPR;
-    (void) nGPR;
-    (void) pFPR;
-#endif
-
 }
 }
 
diff --git a/bridges/source/cpp_uno/gcc3_ios_arm/uno2cpp-arm64.cxx b/bridges/source/cpp_uno/gcc3_ios_arm/uno2cpp-arm64.cxx
new file mode 100644
index 0000000..9b2c676
--- /dev/null
+++ b/bridges/source/cpp_uno/gcc3_ios_arm/uno2cpp-arm64.cxx
@@ -0,0 +1,640 @@
+/* -*- 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 .
+ */
+
+#ifdef __arm64
+
+#include <com/sun/star/uno/RuntimeException.hpp>
+
+#include "bridges/cpp_uno/shared/bridge.hxx"
+#include "bridges/cpp_uno/shared/types.hxx"
+#include "bridges/cpp_uno/shared/unointerfaceproxy.hxx"
+#include "bridges/cpp_uno/shared/vtables.hxx"
+
+#include "share.hxx"
+
+using namespace ::com::sun::star::uno;
+
+namespace arm
+{
+    bool is_complex_struct(const typelib_TypeDescription * type)
+    {
+        const typelib_CompoundTypeDescription * p
+            = reinterpret_cast< const typelib_CompoundTypeDescription * >(type);
+        for (sal_Int32 i = 0; i < p->nMembers; ++i)
+        {
+            if (p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_STRUCT ||
+                p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_EXCEPTION)
+            {
+                typelib_TypeDescription * t = 0;
+                TYPELIB_DANGER_GET(&t, p->ppTypeRefs[i]);
+                bool b = is_complex_struct(t);
+                TYPELIB_DANGER_RELEASE(t);
+                if (b) {
+                    return true;
+                }
+            }
+            else if (!bridges::cpp_uno::shared::isSimpleType(p->ppTypeRefs[i]->eTypeClass))
+                return true;
+        }
+        if (p->pBaseTypeDescription != 0)
+            return is_complex_struct(&p->pBaseTypeDescription->aBase);
+        return false;
+    }
+
+#ifdef __ARM_PCS_VFP
+    bool is_float_only_struct(const typelib_TypeDescription * type)
+    {
+        const typelib_CompoundTypeDescription * p
+            = reinterpret_cast< const typelib_CompoundTypeDescription * >(type);
+        for (sal_Int32 i = 0; i < p->nMembers; ++i)
+        {
+            if (p->ppTypeRefs[i]->eTypeClass != typelib_TypeClass_FLOAT &&
+                p->ppTypeRefs[i]->eTypeClass != typelib_TypeClass_DOUBLE)
+                return false;
+        }
+        return true;
+    }
+#endif
+    bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef )
+    {
+        if (bridges::cpp_uno::shared::isSimpleType(pTypeRef))
+            return false;
+        else if (pTypeRef->eTypeClass == typelib_TypeClass_STRUCT || pTypeRef->eTypeClass == typelib_TypeClass_EXCEPTION)
+        {
+            typelib_TypeDescription * pTypeDescr = 0;
+            TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
+
+            // A Composite Type not larger than 16 bytes is returned in x0, x1
+            // FIXME: what about the "complex struct" thing, is that relevant at all?
+            bool bRet = pTypeDescr->nSize > 16 || is_complex_struct(pTypeDescr);
+
+#ifdef __ARM_PCS_VFP
+            // In the VFP ABI, structs with only float/double values that fit in
+            // 16 bytes are returned in registers
+            if( pTypeDescr->nSize <= 16 && is_float_only_struct(pTypeDescr))
+                bRet = false;
+#endif
+
+            TYPELIB_DANGER_RELEASE( pTypeDescr );
+            return bRet;
+        }
+        return true;
+    }
+}
+
+void MapReturn(sal_uInt32 r0, sal_uInt32 r1, typelib_TypeDescriptionReference * pReturnType, sal_uInt32* pRegisterReturn)
+{
+    switch( pReturnType->eTypeClass )
+    {
+        case typelib_TypeClass_HYPER:
+        case typelib_TypeClass_UNSIGNED_HYPER:
+            pRegisterReturn[1] = r1;
+        case typelib_TypeClass_LONG:
+        case typelib_TypeClass_UNSIGNED_LONG:
+        case typelib_TypeClass_ENUM:
+        case typelib_TypeClass_CHAR:
+        case typelib_TypeClass_SHORT:
+        case typelib_TypeClass_UNSIGNED_SHORT:
+        case typelib_TypeClass_BOOLEAN:
+        case typelib_TypeClass_BYTE:
+            pRegisterReturn[0] = r0;
+            break;
+        case typelib_TypeClass_FLOAT:
+#if !defined(__ARM_PCS_VFP) && (defined(__ARM_EABI__) || defined(__SOFTFP__) || defined(IOS))
+            pRegisterReturn[0] = r0;
+#else
+            register float fret asm("s0");
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wuninitialized"
+            *(float*)pRegisterReturn = fret;
+#pragma GCC diagnostic pop
+#endif
+            break;
+        case typelib_TypeClass_DOUBLE:
+#if !defined(__ARM_PCS_VFP) && (defined(__ARM_EABI__) || defined(__SOFTFP__) || defined(IOS))
+            pRegisterReturn[1] = r1;
+            pRegisterReturn[0] = r0;
+#else
+            register double dret asm("d0");
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wuninitialized"
+            *(double*)pRegisterReturn = dret;
+#pragma GCC diagnostic pop
+#endif
+            break;
+        case typelib_TypeClass_STRUCT:
+        case typelib_TypeClass_EXCEPTION:
+        {
+            if (!arm::return_in_hidden_param(pReturnType))
+                pRegisterReturn[0] = r0;
+            break;
+        }
+        default:
+            break;
+    }
+}
+
+namespace
+{
+//================================================================
+
+void callVirtualMethod(
+    void * pThis,
+    sal_Int32 nVtableIndex,
+    void * pRegisterReturn,
+    typelib_TypeDescriptionReference * pReturnType,
+    sal_uInt32 *pStack,
+    sal_uInt32 nStack,
+    sal_uInt32 *pGPR,
+    sal_uInt32 nGPR,
+    double *pFPR) __attribute__((noinline));
+
+void callVirtualMethod(
+    void * pThis,
+    sal_Int32 nVtableIndex,
+    void * pRegisterReturn,
+    typelib_TypeDescriptionReference * pReturnType,
+    sal_uInt32 *pStack,
+    sal_uInt32 nStack,
+    sal_uInt32 *pGPR,
+    sal_uInt32 nGPR,
+    double *pFPR)
+{
+    abort(); // arm64 code not yet implemented
+
+    (void) pThis;
+    (void) nVtableIndex;
+    (void) pRegisterReturn;
+    (void) pReturnType;
+    (void) pStack;
+    (void) nStack;
+    (void) pGPR;
+    (void) nGPR;
+    (void) pFPR;
+}
+}
+
+#define INSERT_INT32( pSV, nr, pGPR, pDS ) \
+        if ( nr < arm::MAX_GPR_REGS ) \
+                pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \
+        else \
+                *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV );
+
+#ifdef __ARM_EABI__
+#define INSERT_INT64( pSV, nr, pGPR, pDS, pStart ) \
+        if ( (nr < arm::MAX_GPR_REGS) && (nr % 2) ) \
+        { \
+                ++nr; \
+        } \
+        if ( nr < arm::MAX_GPR_REGS ) \
+        { \
+                pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \
+                pGPR[nr++] = *(reinterpret_cast<sal_uInt32 *>( pSV ) + 1); \
+        } \
+        else \
+    { \
+        if ( (pDS - pStart) % 2) \
+                { \
+                    ++pDS; \
+                } \
+                *pDS++ = reinterpret_cast<sal_uInt32 *>( pSV )[0]; \
+                *pDS++ = reinterpret_cast<sal_uInt32 *>( pSV )[1]; \
+    }
+#else
+#define INSERT_INT64( pSV, nr, pGPR, pDS, pStart ) \
+        INSERT_INT32( pSV, nr, pGPR, pDS ) \
+        INSERT_INT32( ((sal_uInt32*)pSV)+1, nr, pGPR, pDS )
+#endif
+
+#ifdef __ARM_PCS_VFP
+// Since single and double arguments share the same register bank the filling of the
+// registers is not always linear. Single values go to the first available single register,
+// while doubles need to have an 8 byte alignment, so only go into double registers starting
+// at every other single register. For ex a float, double, float sequence will fill registers
+// s0, d1, and s1, actually corresponding to the linear order s0,s1, d1.
+//
+// These use the single/double register array and counters and ignore the pGPR argument
+// nSR and nDR are the number of single and double precision registers that are no longer
+// available
+#define INSERT_FLOAT( pSV, nr, pGPR, pDS ) \
+        if (nSR % 2 == 0) {\
+            nSR = 2*nDR; \
+        }\
+        if ( nSR < arm::MAX_FPR_REGS*2 ) {\
+                pSPR[nSR++] = *reinterpret_cast<float *>( pSV ); \
+                if ((nSR % 2 == 1) && (nSR > 2*nDR)) {\
+                    nDR++; \
+                }\
+        }\
+        else \
+        {\
+                *pDS++ = *reinterpret_cast<float *>( pSV );\
+        }
+#define INSERT_DOUBLE( pSV, nr, pGPR, pDS, pStart ) \
+        if ( nDR < arm::MAX_FPR_REGS ) { \
+                pFPR[nDR++] = *reinterpret_cast<double *>( pSV ); \
+        }\
+        else\
+        {\
+            if ( (pDS - pStart) % 2) \
+                { \
+                    ++pDS; \
+                } \
+            *(double *)pDS = *reinterpret_cast<double *>( pSV );\
+            pDS += 2;\
+        }
+#else
+#define INSERT_FLOAT( pSV, nr, pFPR, pDS ) \
+        INSERT_INT32( pSV, nr, pGPR, pDS )
+
+#define INSERT_DOUBLE( pSV, nr, pFPR, pDS, pStart ) \
+        INSERT_INT64( pSV, nr, pGPR, pDS, pStart )
+#endif
+
+#define INSERT_INT16( pSV, nr, pGPR, pDS ) \
+        if ( nr < arm::MAX_GPR_REGS ) \
+                pGPR[nr++] = *reinterpret_cast<sal_uInt16 *>( pSV ); \
+        else \
+                *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV );
+
+#define INSERT_INT8( pSV, nr, pGPR, pDS ) \
+        if ( nr < arm::MAX_GPR_REGS ) \
+                pGPR[nr++] = *reinterpret_cast<sal_uInt8 *>( pSV ); \
+        else \
+                *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV );
+
+namespace {
+//=======================================================================
+static void cpp_call(
+    bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
+    bridges::cpp_uno::shared::VtableSlot aVtableSlot,
+    typelib_TypeDescriptionReference * pReturnTypeRef,
+    sal_Int32 nParams, typelib_MethodParameter * pParams,
+    void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc )
+{
+    // max space for: [complex ret ptr], values|ptr ...
+    sal_uInt32 * pStack = (sal_uInt32 *)__builtin_alloca(
+        sizeof(sal_Int32) + ((nParams+2) * sizeof(sal_Int64)) );
+    sal_uInt32 * pStackStart = pStack;
+
+    sal_uInt32 pGPR[arm::MAX_GPR_REGS];
+    sal_uInt32 nGPR = 0;
+
+    // storage and counters for single and double precision VFP registers
+    double pFPR[arm::MAX_FPR_REGS];
+#ifdef __ARM_PCS_VFP
+    sal_uInt32 nDR = 0;
+    float *pSPR = reinterpret_cast< float *>(&pFPR);
+    sal_uInt32 nSR = 0;
+#endif
+
+    // return
+    typelib_TypeDescription * pReturnTypeDescr = 0;
+    TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
+    OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" );
+
+    void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
+
+    bool bSimpleReturn = true;
+    if (pReturnTypeDescr)
+    {
+        if (arm::return_in_hidden_param( pReturnTypeRef ) )
+            bSimpleReturn = false;
+
+        if (bSimpleReturn)
+            pCppReturn = pUnoReturn; // direct way for simple types
+        else
+        {
+            // complex return via ptr
+            pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
+                    ? __builtin_alloca( pReturnTypeDescr->nSize )
+                    : pUnoReturn); // direct way
+
+            INSERT_INT32( &pCppReturn, nGPR, pGPR, pStack );
+        }
+    }
+    // push this
+    void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI())
+        + aVtableSlot.offset;
+    INSERT_INT32( &pAdjustedThisPtr, nGPR, pGPR, pStack );
+
+    // stack space
+    OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" );
+    // args
+    void ** pCppArgs  = (void **)alloca( 3 * sizeof(void *) * nParams );
+    // indices of values this have to be converted (interface conversion cpp<=>uno)
+    sal_Int32 * pTempIndices = (sal_Int32 *)(pCppArgs + nParams);
+    // type descriptions for reconversions
+    typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
+
+    sal_Int32 nTempIndices   = 0;
+
+    for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
+    {
+        const typelib_MethodParameter & rParam = pParams[nPos];
+        typelib_TypeDescription * pParamTypeDescr = 0;
+        TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
+
+        if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
+        {
+//            uno_copyAndConvertData( pCppArgs[nPos] = pStack, pUnoArgs[nPos],
+            uno_copyAndConvertData( pCppArgs[nPos] = alloca(8), pUnoArgs[nPos],
+                pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
+
+            switch (pParamTypeDescr->eTypeClass)
+            {
+            case typelib_TypeClass_HYPER:
+            case typelib_TypeClass_UNSIGNED_HYPER:
+
+                SAL_INFO( "bridges.ios", "hyper is " << pCppArgs[nPos] );
+
+                INSERT_INT64( pCppArgs[nPos], nGPR, pGPR, pStack, pStackStart );
+                break;
+            case typelib_TypeClass_LONG:
+            case typelib_TypeClass_UNSIGNED_LONG:
+            case typelib_TypeClass_ENUM:
+
+                SAL_INFO( "bridges.ios", "long is " << pCppArgs[nPos] );
+
+                INSERT_INT32( pCppArgs[nPos], nGPR, pGPR, pStack );
+                break;
+            case typelib_TypeClass_SHORT:
+            case typelib_TypeClass_CHAR:
+            case typelib_TypeClass_UNSIGNED_SHORT:
+                INSERT_INT16( pCppArgs[nPos], nGPR, pGPR, pStack );
+                break;
+            case typelib_TypeClass_BOOLEAN:
+            case typelib_TypeClass_BYTE:
+                INSERT_INT8( pCppArgs[nPos], nGPR, pGPR, pStack );
+                break;
+            case typelib_TypeClass_FLOAT:
+                INSERT_FLOAT( pCppArgs[nPos], nGPR, pGPR, pStack );
+                break;
+            case typelib_TypeClass_DOUBLE:
+                INSERT_DOUBLE( pCppArgs[nPos], nGPR, pGPR, pStack, pStackStart );
+                break;
+            default:
+                break;
+            }
+            // no longer needed
+            TYPELIB_DANGER_RELEASE( pParamTypeDescr );
+        }
+        else // ptr to complex value | ref
+        {
+            if (! rParam.bIn) // is pure out
+            {
+                // cpp out is constructed mem, uno out is not!
+                uno_constructData(
+                    pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
+                    pParamTypeDescr );
+                pTempIndices[nTempIndices] = nPos; // default constructed for cpp call
+                // will be released at reconversion
+                ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
+            }
+            // is in/inout
+            else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
+            {
+                uno_copyAndConvertData(
+                    pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
+                    pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
+
+                pTempIndices[nTempIndices] = nPos; // has to be reconverted
+                // will be released at reconversion
+                ppTempParamTypeDescr[nTempIndices++] = pParamTypeDescr;
+            }
+            else // direct way
+            {
+                pCppArgs[nPos] = pUnoArgs[nPos];
+                // no longer needed
+                TYPELIB_DANGER_RELEASE( pParamTypeDescr );
+            }
+            INSERT_INT32( &(pCppArgs[nPos]), nGPR, pGPR, pStack );
+        }
+    }
+
+    try
+    {
+        callVirtualMethod(
+            pAdjustedThisPtr, aVtableSlot.index,
+            pCppReturn, pReturnTypeRef,
+            pStackStart,
+            (pStack - pStackStart),
+            pGPR, nGPR,
+            pFPR);
+
+        // NO exception occurred...
+        *ppUnoExc = 0;
+
+        // reconvert temporary params
+        for ( ; nTempIndices--; )
+        {
+            sal_Int32 nIndex = pTempIndices[nTempIndices];
+            typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndices];
+
+            if (pParams[nIndex].bIn)
+            {
+                if (pParams[nIndex].bOut) // inout
+                {
+                    uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value
+                    uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
+                                            pThis->getBridge()->getCpp2Uno() );
+                }
+            }
+            else // pure out
+            {
+                uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
+                                        pThis->getBridge()->getCpp2Uno() );
+            }
+            // destroy temp cpp param => cpp: every param was constructed
+            uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
+
+            TYPELIB_DANGER_RELEASE( pParamTypeDescr );
+        }
+        // return value
+        if (pCppReturn && pUnoReturn != pCppReturn)
+        {
+            uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
+                                    pThis->getBridge()->getCpp2Uno() );
+            uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release );
+        }
+    }
+    catch (...)
+    {
+//        __asm__ __volatile__ ("sub sp, sp, #2048\n");
+
+        // fill uno exception
+        CPPU_CURRENT_NAMESPACE::fillUnoException( abi::__cxa_get_globals()->caughtExceptions, *ppUnoExc, pThis->getBridge()->getCpp2Uno() );
+
+        // temporary params
+        for ( ; nTempIndices--; )
+        {
+            sal_Int32 nIndex = pTempIndices[nTempIndices];
+            // destroy temp cpp param => cpp: every param was constructed
+            uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndices], cpp_release );
+            TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndices] );
+        }
+
+        // return type
+        if (pReturnTypeDescr)
+            TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
+    }
+}
+}
+
+namespace bridges { namespace cpp_uno { namespace shared {
+
+void unoInterfaceProxyDispatch(
+    uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
+    void * pReturn, void * pArgs[], uno_Any ** ppException )
+{
+    // is my surrogate
+    bridges::cpp_uno::shared::UnoInterfaceProxy * pThis
+          = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI);
+#if OSL_DEBUG_LEVEL > 0
+    typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
+#endif
+
+    switch (pMemberDescr->eTypeClass)
+    {
+    case typelib_TypeClass_INTERFACE_ATTRIBUTE:
+    {
+#if OSL_DEBUG_LEVEL > 0
+        // determine vtable call index
+        sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
+        OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" );
+#endif
+
+        VtableSlot aVtableSlot(
+            getVtableSlot(
+            reinterpret_cast<typelib_InterfaceAttributeTypeDescription const *>
+              (pMemberDescr)));
+
+        if (pReturn)
+        {
+            // dependent dispatch
+            cpp_call(
+                pThis, aVtableSlot,
+                ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
+                0, 0, // no params
+                pReturn, pArgs, ppException );
+        }
+        else
+        {
+            // is SET
+            typelib_MethodParameter aParam;
+            aParam.pTypeRef =
+                ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
+            aParam.bIn      = sal_True;
+            aParam.bOut     = sal_False;
+
+            typelib_TypeDescriptionReference * pReturnTypeRef = 0;
+            OUString aVoidName("void");
+            typelib_typedescriptionreference_new(
+                &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
+
+            // dependent dispatch
+            aVtableSlot.index += 1;
+            cpp_call(
+                pThis, aVtableSlot, // get, then set method
+                pReturnTypeRef,
+                1, &aParam,
+                pReturn, pArgs, ppException );
+
+            typelib_typedescriptionreference_release( pReturnTypeRef );
+        }
+
+        break;
+    }
+    case typelib_TypeClass_INTERFACE_METHOD:
+    {
+#if OSL_DEBUG_LEVEL > 0
+        // determine vtable call index
+        sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
+        OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" );
+#endif
+
+        VtableSlot aVtableSlot(
+            getVtableSlot(
+            reinterpret_cast<typelib_InterfaceMethodTypeDescription const *>
+              (pMemberDescr)));
+
+        switch (aVtableSlot.index)
+        {
+            // standard calls
+        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< 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()
+        default:
+            // dependent dispatch
+            cpp_call(
+                pThis, aVtableSlot,
+                ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
+                ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
+                ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
+                pReturn, pArgs, ppException );
+        }
+        break;
+    }
+    default:
+    {
+        ::com::sun::star::uno::RuntimeException aExc(
+            OUString("illegal member type description!"),
+            ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
+
+        Type const & rExcType = ::getCppuType( &aExc );
+        // binary identical null reference
+        ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
+    }
+    }
+}
+
+} } }
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */


More information about the Libreoffice-commits mailing list