xref: /trunk/main/bridges/source/cpp_uno/s5abi_macosx_aarch64/uno2cpp.cxx (revision 32e61489b21963d4717517b977c5849c239c63df)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_bridges.hxx"
26 
27 #include <exception>
28 #include <typeinfo>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 
33 #include "rtl/alloc.h"
34 #include "rtl/ustrbuf.hxx"
35 
36 #include <com/sun/star/uno/genfunc.hxx>
37 #include "com/sun/star/uno/RuntimeException.hpp"
38 #include <uno/data.h>
39 
40 #include <bridges/cpp_uno/shared/bridge.hxx>
41 #include <bridges/cpp_uno/shared/types.hxx>
42 #include "bridges/cpp_uno/shared/unointerfaceproxy.hxx"
43 #include "bridges/cpp_uno/shared/vtables.hxx"
44 
45 #include "abi.hxx"
46 #include "share.hxx"
47 
48 using namespace ::rtl;
49 using namespace ::com::sun::star::uno;
50 
51 //==================================================================================================
52 
53 // The AArch64 outgoing-call trampoline, implemented in call.s.  It loads the
54 // argument registers from the caller-prepared arrays, copies overflow args to
55 // the outgoing stack, performs the indirect call, and returns x0/x1 and d0..d3.
56 extern "C" void callVirtualFunction(
57     sal_uInt64 pFunction, sal_uInt64 pIndirectRet,
58     sal_uInt64 *pGPR, double *pFPR,
59     sal_uInt64 *pStack, sal_uInt32 nStackWords,
60     sal_uInt64 *pGPRReturn, double *pFPRReturn );
61 
62 static void callVirtualMethod(void * pThis, sal_uInt32 nVtableIndex,
63                               void * pRegisterReturn, typelib_TypeDescriptionReference * pReturnTypeRef, bool bSimpleReturn,
64                               void * pIndirectReturn,
65                               sal_uInt64 *pStack, sal_uInt32 nStack,
66                               sal_uInt64 *pGPR, sal_uInt32 nGPR,
67                               double *pFPR, sal_uInt32 nFPR) __attribute__((noinline));
68 
69 static void callVirtualMethod(void * pThis, sal_uInt32 nVtableIndex,
70                               void * pRegisterReturn, typelib_TypeDescriptionReference * pReturnTypeRef, bool bSimpleReturn,
71                               void * pIndirectReturn,
72                               sal_uInt64 *pStack, sal_uInt32 nStack,
73                               sal_uInt64 *pGPR, sal_uInt32 nGPR,
74                               double *pFPR, sal_uInt32 nFPR)
75 {
76 #if OSL_DEBUG_LEVEL > 1
77     // Let's figure out what is really going on here
78     {
79         fprintf( stderr, "= callVirtualMethod() =\nGPR's (%d): ", nGPR );
80         for ( unsigned int i = 0; i < nGPR; ++i )
81             fprintf( stderr, "0x%lx, ", pGPR[i] );
82         fprintf( stderr, "\nFPR's (%d): ", nFPR );
83         for ( unsigned int i = 0; i < nFPR; ++i )
84             fprintf( stderr, "%f, ", pFPR[i] );
85         fprintf( stderr, "\nStack (%d): ", nStack );
86         for ( unsigned int i = 0; i < nStack; ++i )
87             fprintf( stderr, "0x%lx, ", pStack[i] );
88         fprintf( stderr, "\n" );
89     }
90 #endif
91 
92     // The call instruction within callVirtualFunction may throw exceptions.  So
93     // that the compiler handles this correctly, it is important that (a)
94     // callVirtualMethod might call dummy_can_throw_anything (although this never
95     // happens at runtime), which in turn can throw exceptions, and (b)
96     // callVirtualMethod is not inlined at its call site (so that any exceptions
97     // thrown across the call are caught):
98     if ( !pThis )
99         CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything( "xxx" ); // address something
100 
101     // Should not happen, but...
102     if ( nFPR > aarch64::MAX_FPR_REGS )
103         nFPR = aarch64::MAX_FPR_REGS;
104     if ( nGPR > aarch64::MAX_GPR_REGS )
105         nGPR = aarch64::MAX_GPR_REGS;
106 
107     // Get pointer to the C++ virtual method from the vtable.
108     sal_uInt64 pMethod = *((sal_uInt64 *)pThis);
109     pMethod += 8 * nVtableIndex;
110     pMethod = *((sal_uInt64 *)pMethod);
111 
112     // Return register save areas: x0,x1 and d0..d3 (HFA up to 4 elements).
113     sal_uInt64 gpReturn[2] = { 0, 0 };
114     double fpReturn[4] = { 0, 0, 0, 0 };
115 
116     // Ensure the GPR/FPR arrays are the full register width even if fewer were
117     // filled (the trampoline always loads all 8 of each).
118     sal_uInt64 gpr[aarch64::MAX_GPR_REGS];
119     double fpr[aarch64::MAX_FPR_REGS];
120     for ( sal_uInt32 i = 0; i < aarch64::MAX_GPR_REGS; ++i )
121         gpr[i] = ( i < nGPR ) ? pGPR[i] : 0;
122     for ( sal_uInt32 i = 0; i < aarch64::MAX_FPR_REGS; ++i )
123         fpr[i] = ( i < nFPR ) ? pFPR[i] : 0;
124 
125     callVirtualFunction(
126         pMethod,
127         reinterpret_cast<sal_uInt64>( pIndirectReturn ), // x8, 0 if none
128         gpr, fpr,
129         pStack, nStack,
130         gpReturn, fpReturn );
131 
132     switch (pReturnTypeRef->eTypeClass)
133     {
134     case typelib_TypeClass_HYPER:
135     case typelib_TypeClass_UNSIGNED_HYPER:
136         *reinterpret_cast<sal_uInt64 *>( pRegisterReturn ) = gpReturn[0];
137         break;
138     case typelib_TypeClass_LONG:
139     case typelib_TypeClass_UNSIGNED_LONG:
140     case typelib_TypeClass_ENUM:
141         *reinterpret_cast<sal_uInt32 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt32*>( &gpReturn[0] );
142         break;
143     case typelib_TypeClass_CHAR:
144     case typelib_TypeClass_SHORT:
145     case typelib_TypeClass_UNSIGNED_SHORT:
146         *reinterpret_cast<sal_uInt16 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt16*>( &gpReturn[0] );
147         break;
148     case typelib_TypeClass_BOOLEAN:
149     case typelib_TypeClass_BYTE:
150         *reinterpret_cast<sal_uInt8 *>( pRegisterReturn ) = *reinterpret_cast<sal_uInt8*>( &gpReturn[0] );
151         break;
152     case typelib_TypeClass_FLOAT:
153     case typelib_TypeClass_DOUBLE:
154         *reinterpret_cast<double *>( pRegisterReturn ) = fpReturn[0];
155         break;
156     default:
157         {
158             sal_Int32 const nRetSize = pReturnTypeRef->pType->nSize;
159             if (bSimpleReturn && nRetSize <= 16 && nRetSize > 0)
160             {
161                 // Register-returned aggregate: an HFA arrives in d0..d3, a
162                 // non-HFA <= 16 bytes in x0,x1.  fill_struct picks the right one.
163                 aarch64::fill_struct( pReturnTypeRef, &gpReturn[0], &fpReturn[0], pRegisterReturn);
164             }
165             break;
166         }
167     }
168 }
169 
170 //==================================================================================================
171 
172 // Macros for easier insertion of values to registers or stack
173 // pSV - pointer to the source
174 // nr - order of the value [will be increased if stored to register]
175 // pFPR, pGPR - pointer to the registers
176 // pDS - pointer to the stack [will be increased if stored here]
177 
178 // The pFPR slot holds the value to be loaded into a v register; the trampoline
179 // loads it with LDR d<n>, so float and double are stored the same way here.
180 #define INSERT_FLOAT_DOUBLE( pSV, nr, pFPR, pDS ) \
181     if ( nr < aarch64::MAX_FPR_REGS ) \
182         pFPR[nr++] = *reinterpret_cast<double *>( pSV ); \
183     else \
184         *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); // verbatim!
185 
186 #define INSERT_INT64( pSV, nr, pGPR, pDS ) \
187     if ( nr < aarch64::MAX_GPR_REGS ) \
188         pGPR[nr++] = *reinterpret_cast<sal_uInt64 *>( pSV ); \
189     else \
190         *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV );
191 
192 #define INSERT_INT32( pSV, nr, pGPR, pDS ) \
193     if ( nr < aarch64::MAX_GPR_REGS ) \
194         pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \
195     else \
196         *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV );
197 
198 #define INSERT_INT16( pSV, nr, pGPR, pDS ) \
199     if ( nr < aarch64::MAX_GPR_REGS ) \
200         pGPR[nr++] = *reinterpret_cast<sal_uInt16 *>( pSV ); \
201     else \
202         *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV );
203 
204 #define INSERT_INT8( pSV, nr, pGPR, pDS ) \
205     if ( nr < aarch64::MAX_GPR_REGS ) \
206         pGPR[nr++] = *reinterpret_cast<sal_uInt8 *>( pSV ); \
207     else \
208         *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV );
209 
210 //==================================================================================================
211 
212 namespace {
213 
214 void appendCString(OUStringBuffer & buffer, char const * text) {
215     if (text != 0) {
216         buffer.append(
217             OStringToOUString(OString(text), RTL_TEXTENCODING_ISO_8859_1));
218             // use 8859-1 to avoid conversion failure
219     }
220 }
221 
222 }
223 
224 static void cpp_call(
225     bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
226     bridges::cpp_uno::shared::VtableSlot aVtableSlot,
227     typelib_TypeDescriptionReference * pReturnTypeRef,
228     sal_Int32 nParams, typelib_MethodParameter * pParams,
229     void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc )
230 {
231     // Maxium space for [complex ret ptr], values | ptr ...
232     // (but will be used less - some of the values will be in pGPR and pFPR)
233     sal_uInt64 *pStack = (sal_uInt64 *)__builtin_alloca( (nParams + 3) * sizeof(sal_uInt64) );
234     sal_uInt64 *pStackStart = pStack;
235 
236     sal_uInt64 pGPR[aarch64::MAX_GPR_REGS];
237     sal_uInt32 nGPR = 0;
238 
239     double pFPR[aarch64::MAX_FPR_REGS];
240     sal_uInt32 nFPR = 0;
241 
242     // Return
243     typelib_TypeDescription * pReturnTypeDescr = 0;
244     TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
245     OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" );
246 
247     void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion (see below)
248 
249     // Indirect-result pointer. On AArch64 this is passed in the dedicated x8
250     // register, NOT as the first general-purpose argument (unlike x86-64 SysV).
251     // So we do NOT insert it into pGPR here; it is threaded to the trampoline
252     // separately as pIndirectReturn.
253     void * pIndirectReturn = 0;
254 
255     bool bSimpleReturn = true;
256     if ( pReturnTypeDescr )
257     {
258         if ( aarch64::return_in_hidden_param( pReturnTypeRef ) )
259             bSimpleReturn = false;
260 
261         if ( bSimpleReturn )
262             pCppReturn = pUnoReturn; // direct way for simple types
263         else
264         {
265             // complex return via the x8 indirect-result buffer
266             pCppReturn = bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )?
267                          __builtin_alloca( pReturnTypeDescr->nSize ) : pUnoReturn;
268             pIndirectReturn = pCppReturn;
269         }
270     }
271 
272     // Push "this" pointer
273     void * pAdjustedThisPtr = reinterpret_cast< void ** >( pThis->getCppI() ) + aVtableSlot.offset;
274     INSERT_INT64( &pAdjustedThisPtr, nGPR, pGPR, pStack );
275 
276     // Args
277     void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams );
278     // Indizes of values this have to be converted (interface conversion cpp<=>uno)
279     sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams);
280     // Type descriptions for reconversions
281     typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
282 
283     sal_Int32 nTempIndizes = 0;
284 
285     for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
286     {
287         const typelib_MethodParameter & rParam = pParams[nPos];
288         typelib_TypeDescription * pParamTypeDescr = 0;
289         TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
290 
291         if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
292         {
293             uno_copyAndConvertData( pCppArgs[nPos] = alloca( 8 ), pUnoArgs[nPos], pParamTypeDescr,
294                                     pThis->getBridge()->getUno2Cpp() );
295 
296             switch (pParamTypeDescr->eTypeClass)
297             {
298             case typelib_TypeClass_HYPER:
299             case typelib_TypeClass_UNSIGNED_HYPER:
300                 INSERT_INT64( pCppArgs[nPos], nGPR, pGPR, pStack );
301                 break;
302             case typelib_TypeClass_LONG:
303             case typelib_TypeClass_UNSIGNED_LONG:
304             case typelib_TypeClass_ENUM:
305                 INSERT_INT32( pCppArgs[nPos], nGPR, pGPR, pStack );
306                 break;
307             case typelib_TypeClass_SHORT:
308             case typelib_TypeClass_CHAR:
309             case typelib_TypeClass_UNSIGNED_SHORT:
310                 INSERT_INT16( pCppArgs[nPos], nGPR, pGPR, pStack );
311                 break;
312             case typelib_TypeClass_BOOLEAN:
313             case typelib_TypeClass_BYTE:
314                 INSERT_INT8( pCppArgs[nPos], nGPR, pGPR, pStack );
315                 break;
316             case typelib_TypeClass_FLOAT:
317             case typelib_TypeClass_DOUBLE:
318                 INSERT_FLOAT_DOUBLE( pCppArgs[nPos], nFPR, pFPR, pStack );
319                 break;
320             default:
321                 break;
322             }
323 
324             // no longer needed
325             TYPELIB_DANGER_RELEASE( pParamTypeDescr );
326         }
327         else // ptr to complex value | ref
328         {
329             if (! rParam.bIn) // is pure out
330             {
331                 // cpp out is constructed mem, uno out is not!
332                 uno_constructData(
333                     pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
334                     pParamTypeDescr );
335                 pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call
336                 // will be released at reconversion
337                 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
338             }
339             // is in/inout
340             else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
341             {
342                 uno_copyAndConvertData(
343                     pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
344                     pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
345 
346                 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
347                 // will be released at reconversion
348                 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
349             }
350             else // direct way
351             {
352                 pCppArgs[nPos] = pUnoArgs[nPos];
353                 // no longer needed
354                 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
355             }
356             INSERT_INT64( &(pCppArgs[nPos]), nGPR, pGPR, pStack );
357         }
358     }
359 
360     try
361     {
362         try {
363             callVirtualMethod(
364                 pAdjustedThisPtr, aVtableSlot.index,
365                 pCppReturn, pReturnTypeRef, bSimpleReturn,
366                 pIndirectReturn,
367                 pStackStart, ( pStack - pStackStart ),
368                 pGPR, nGPR,
369                 pFPR, nFPR );
370         } catch (Exception &) {
371             throw;
372         } catch (std::exception & e) {
373             OUStringBuffer buf;
374             buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("C++ code threw "));
375             appendCString(buf, typeid(e).name());
376             buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(": "));
377             appendCString(buf, e.what());
378             throw RuntimeException(
379                 buf.makeStringAndClear(), Reference< XInterface >());
380         } catch (...) {
381             throw RuntimeException(
382                 OUString(
383                     RTL_CONSTASCII_USTRINGPARAM(
384                         "C++ code threw unknown exception")),
385                 Reference< XInterface >());
386         }
387 
388         // NO exception occurred...
389         *ppUnoExc = 0;
390 
391         // reconvert temporary params
392         for ( ; nTempIndizes--; )
393         {
394             sal_Int32 nIndex = pTempIndizes[nTempIndizes];
395             typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
396 
397             if (pParams[nIndex].bIn)
398             {
399                 if (pParams[nIndex].bOut) // inout
400                 {
401                     uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value
402                     uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
403                                             pThis->getBridge()->getCpp2Uno() );
404                 }
405             }
406             else // pure out
407             {
408                 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
409                                         pThis->getBridge()->getCpp2Uno() );
410             }
411             // destroy temp cpp param => cpp: every param was constructed
412             uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
413 
414             TYPELIB_DANGER_RELEASE( pParamTypeDescr );
415         }
416         // return value
417         if (pCppReturn && pUnoReturn != pCppReturn)
418         {
419             uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
420                                     pThis->getBridge()->getCpp2Uno() );
421             uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release );
422         }
423     }
424     catch (...)
425     {
426         // fill uno exception
427         fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions, *ppUnoExc, pThis->getBridge()->getCpp2Uno() );
428 
429         // temporary params
430         for ( ; nTempIndizes--; )
431         {
432             sal_Int32 nIndex = pTempIndizes[nTempIndizes];
433             // destroy temp cpp param => cpp: every param was constructed
434             uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release );
435             TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
436         }
437         // return type
438         if (pReturnTypeDescr)
439             TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
440     }
441 }
442 
443 //==================================================================================================
444 
445 namespace bridges { namespace cpp_uno { namespace shared {
446 
447 void unoInterfaceProxyDispatch(
448     uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
449     void * pReturn, void * pArgs[], uno_Any ** ppException )
450 {
451     // is my surrogate
452     bridges::cpp_uno::shared::UnoInterfaceProxy * pThis
453         = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI);
454 #if OSL_DEBUG_LEVEL > 0
455     typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
456 #endif
457 
458     switch (pMemberDescr->eTypeClass)
459     {
460     case typelib_TypeClass_INTERFACE_ATTRIBUTE:
461     {
462 #if OSL_DEBUG_LEVEL > 0
463         // determine vtable call index
464         sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
465         OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" );
466 #endif
467         VtableSlot aVtableSlot(
468                 getVtableSlot(
469                     reinterpret_cast<
470                     typelib_InterfaceAttributeTypeDescription const * >(
471                         pMemberDescr)));
472 
473         if (pReturn)
474         {
475             // dependent dispatch
476             cpp_call(
477                 pThis, aVtableSlot,
478                 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
479                 0, 0, // no params
480                 pReturn, pArgs, ppException );
481         }
482         else
483         {
484             // is SET
485             typelib_MethodParameter aParam;
486             aParam.pTypeRef =
487                 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
488             aParam.bIn      = sal_True;
489             aParam.bOut     = sal_False;
490 
491             typelib_TypeDescriptionReference * pReturnTypeRef = 0;
492             OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") );
493             typelib_typedescriptionreference_new(
494                 &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
495 
496             // dependent dispatch
497             aVtableSlot.index += 1; // get, then set method
498             cpp_call(
499                 pThis, aVtableSlot, // get, then set method
500                 pReturnTypeRef,
501                 1, &aParam,
502                 pReturn, pArgs, ppException );
503 
504             typelib_typedescriptionreference_release( pReturnTypeRef );
505         }
506 
507         break;
508     }
509     case typelib_TypeClass_INTERFACE_METHOD:
510     {
511 #if OSL_DEBUG_LEVEL > 0
512         // determine vtable call index
513         sal_Int32 nMemberPos = ((typelib_InterfaceMemberTypeDescription *)pMemberDescr)->nPosition;
514         OSL_ENSURE( nMemberPos < pTypeDescr->nAllMembers, "### member pos out of range!" );
515 #endif
516         VtableSlot aVtableSlot(
517                 getVtableSlot(
518                     reinterpret_cast<
519                     typelib_InterfaceMethodTypeDescription const * >(
520                         pMemberDescr)));
521 
522         switch (aVtableSlot.index)
523         {
524             // standard calls
525         case 1: // acquire uno interface
526             (*pUnoI->acquire)( pUnoI );
527             *ppException = 0;
528             break;
529         case 2: // release uno interface
530             (*pUnoI->release)( pUnoI );
531             *ppException = 0;
532             break;
533         case 0: // queryInterface() opt
534         {
535             typelib_TypeDescription * pTD = 0;
536             TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
537             if (pTD)
538             {
539                 uno_Interface * pInterface = 0;
540                 (*pThis->getBridge()->getUnoEnv()->getRegisteredInterface)(
541                     pThis->getBridge()->getUnoEnv(),
542                     (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
543 
544                 if (pInterface)
545                 {
546                     ::uno_any_construct(
547                         reinterpret_cast< uno_Any * >( pReturn ),
548                         &pInterface, pTD, 0 );
549                     (*pInterface->release)( pInterface );
550                     TYPELIB_DANGER_RELEASE( pTD );
551                     *ppException = 0;
552                     break;
553                 }
554                 TYPELIB_DANGER_RELEASE( pTD );
555             }
556         } // else perform queryInterface()
557         default:
558             // dependent dispatch
559             cpp_call(
560                 pThis, aVtableSlot,
561                 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
562                 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
563                 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
564                 pReturn, pArgs, ppException );
565         }
566         break;
567     }
568     default:
569     {
570         ::com::sun::star::uno::RuntimeException aExc(
571             OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ),
572             ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
573 
574         Type const & rExcType = ::getCppuType( &aExc );
575         // binary identical null reference
576         ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
577     }
578     }
579 }
580 
581 } } }
582