xref: /AOO41X/main/bridges/source/cpp_uno/gcc3_solaris_sparc/uno2cpp.cxx (revision 61dff127b6698e0bae836c8aedd6ec62111483d1)
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 #include <malloc.h>
27 #include <com/sun/star/uno/genfunc.hxx>
28 #include <uno/data.h>
29 
30 #include "bridges/cpp_uno/shared/bridge.hxx"
31 #include "bridges/cpp_uno/shared/types.hxx"
32 #include "bridges/cpp_uno/shared/unointerfaceproxy.hxx"
33 #include "bridges/cpp_uno/shared/vtables.hxx"
34 
35 #include "share.hxx"
36 
37 #include <sal/alloca.h>
38 
39 using namespace rtl;
40 using namespace com::sun::star::uno;
41 
42 namespace
43 {
44 //==================================================================================================
45 // The call instruction within the asm section of callVirtualMethod may throw
46 // exceptions.  So that the compiler handles this correctly, it is important
47 // that (a) callVirtualMethod might call dummy_can_throw_anything (although this
48 // never happens at runtime), which in turn can throw exceptions, and (b)
49 // callVirtualMethod is not inlined at its call site (so that any exceptions are
50 // caught which are thrown from the instruction calling callVirtualMethod):
51 
52 void callVirtualMethod( void * pAdjustedThisPtr,
53                         sal_Int32 nVtableIndex,
54                         void * pRegisterReturn,
55                         typelib_TypeClass eReturnType,
56                         sal_Int32 * pStackLongs,
57                         sal_Int32 nStackLongs ) __attribute__((noinline));
58 
callVirtualMethod(void * pAdjustedThisPtr,sal_Int32 nVtableIndex,void * pRegisterReturn,typelib_TypeClass eReturnType,sal_Int32 * pStackLongs,sal_Int32 nStackLongs)59 void callVirtualMethod( void * pAdjustedThisPtr,
60                         sal_Int32 nVtableIndex,
61                         void * pRegisterReturn,
62                         typelib_TypeClass eReturnType,
63                         sal_Int32 * pStackLongs,
64                         sal_Int32 nStackLongs )
65 {
66     // parameter list is mixed list of * and values
67     // reference parameters are pointers
68 
69     OSL_ENSURE( pStackLongs && pAdjustedThisPtr, "### null ptr!" );
70     OSL_ENSURE( (sizeof(void *) == 4) &&
71                  (sizeof(sal_Int32) == 4), "### unexpected size of int!" );
72     OSL_ENSURE( nStackLongs && pStackLongs, "### no stack in callVirtualMethod !" );
73 
74     // never called
75     if (! pAdjustedThisPtr) CPPU_CURRENT_NAMESPACE::dummy_can_throw_anything("xxx"); // address something
76 
77     volatile long o0 = 0, o1 = 0; // for register returns
78     volatile double f0d = 0;
79     volatile float f0f = 0;
80     volatile long long saveReg[7];
81 
82     __asm__ (
83         // save registers
84         "std %%l0, [%4]\n\t"
85         "mov %4, %%l0\n\t"
86         "mov %%l0, %%l1\n\t"
87         "add %%l0, 8, %%l0\n\t"
88         "std %%l2, [%%l0]\n\t"
89         "add %%l0, 8, %%l0\n\t"
90         "std %%l4, [%%l0]\n\t"
91         "add %%l0, 8, %%l0\n\t"
92         "std %%o0, [%%l0]\n\t"
93         "add %%l0, 8, %%l0\n\t"
94         "std %%o2, [%%l0]\n\t"
95         "add %%l0, 8, %%l0\n\t"
96         "std %%o4, [%%l0]\n\t"
97         "add %%l0, 8, %%l0\n\t"
98         "std %%l6, [%%l0]\n\t"
99         "mov %%l1, %%l7\n\t"
100 
101         // increase our own stackframe if necessary
102         "mov %%sp, %%l3\n\t"        // save stack ptr for readjustment
103 
104         "subcc %%i5, 7, %%l0\n\t"
105         "ble .LmoveOn\n\t"
106         "nop\n\t"
107 
108         "sll %%l0, 2, %%l0\n\t"
109         "add %%l0, 96, %%l0\n\t"
110         "mov %%sp, %%l1\n\t"        // old stack ptr
111         "sub %%sp, %%l0, %%l0\n\t"  // future stack ptr
112         "andcc %%l0, 7, %%g0\n\t"   // align stack to 8
113         "be .LisAligned\n\t"
114         "nop\n\t"
115         "sub %%l0, 4, %%l0\n"
116     ".LisAligned:\n\t"
117         "mov %%l0, %%o5\n\t"            // save newly computed stack ptr
118         "add %%g0, 16, %%o4\n"
119 
120         // now copy longs down to save register window
121         // and local variables
122     ".LcopyDown:\n\t"
123         "ld [%%l1], %%l2\n\t"
124         "st %%l2,[%%l0]\n\t"
125         "add %%l0, 4, %%l0\n\t"
126         "add %%l1, 4, %%l1\n\t"
127         "subcc %%o4, 1, %%o4\n\t"
128         "bne .LcopyDown\n\t"
129 
130         "mov %%o5, %%sp\n\t"        // move new stack ptr (hopefully) atomically
131         // while register window is valid in both spaces
132         // (scheduling might hit in copyDown loop)
133 
134         "sub %%i5, 7, %%l0\n\t"     // copy parameters past the sixth to stack
135         "add %%i4, 28, %%l1\n\t"
136         "add %%sp, 92, %%l2\n"
137     ".LcopyLong:\n\t"
138         "ld [%%l1], %%o0\n\t"
139         "st %%o0, [%%l2]\n\t"
140         "add %%l1, 4, %%l1\n\t"
141         "add %%l2, 4, %%l2\n\t"
142         "subcc %%l0, 1, %%l0\n\t"
143         "bne .LcopyLong\n\t"
144         "nop\n"
145 
146     ".LmoveOn:\n\t"
147         "mov %%i5, %%l0\n\t"        // prepare out registers
148         "mov %%i4, %%l1\n\t"
149 
150         "ld [%%l1], %%o0\n\t"       // prepare complex return ptr
151         "st %%o0, [%%sp+64]\n\t"
152         "sub %%l0, 1, %%l0\n\t"
153         "add %%l1, 4, %%l1\n\t"
154 
155         "ld [%%l1], %%o0\n\t"
156         "subcc %%l0, 1, %%l0\n\t"
157         "be .LdoCall\n\t"
158         "nop\n\t"
159 
160         "add %%l1, 4, %%l1\n\t"
161         "ld [%%l1], %%o1\n\t"
162         "subcc %%l0, 1, %%l0\n\t"
163         "be .LdoCall\n\t"
164         "nop\n\t"
165 
166         "add %%l1, 4, %%l1\n\t"
167         "ld [%%l1], %%o2\n\t"
168         "subcc %%l0, 1, %%l0\n\t"
169         "be .LdoCall\n\t"
170         "nop\n\t"
171 
172         "add %%l1, 4, %%l1\n\t"
173         "ld [%%l1], %%o3\n\t"
174         "subcc %%l0, 1, %%l0\n\t"
175         "be .LdoCall\n\t"
176         "nop\n\t"
177 
178         "add %%l1, 4, %%l1\n\t"
179         "ld [%%l1], %%o4\n\t"
180         "subcc %%l0, 1, %%l0\n\t"
181         "be .LdoCall\n\t"
182         "nop\n\t"
183 
184         "add %%l1, 4, %%l1\n\t"
185         "ld [%%l1], %%o5\n"
186 
187     ".LdoCall:\n\t"
188         "ld [%%i0], %%l0\n\t"       // get vtable ptr
189 
190 "sll %%i1, 2, %%l6\n\t"
191 //        "add %%l6, 8, %%l6\n\t"
192         "add %%l6, %%l0, %%l0\n\t"
193 //      // vtable has 8byte wide entries,
194 //      // upper half contains 2 half words, of which the first
195 //      // is the this ptr patch !
196 //      // first entry is (or __tf)
197 
198 //      "ldsh [%%l0], %%l6\n\t"     // load this ptr patch
199 //      "add %%l6, %%o0, %%o0\n\t"  // patch this ptr
200 
201 //      "add %%l0, 4, %%l0\n\t"     // get virtual function ptr
202         "ld [%%l0], %%l0\n\t"
203 
204         "ld [%%i4], %%l2\n\t"
205         "subcc %%l2, %%g0, %%l2\n\t"
206         "bne .LcomplexCall\n\t"
207         "nop\n\t"
208         "call %%l0\n\t"
209         "nop\n\t"
210         "ba .LcallReturned\n\t"
211         "nop\n"
212     ".LcomplexCall:\n\t"
213         "call %%l0\n\t"
214         "nop\n\t"
215         "unimp\n"
216 
217     ".LcallReturned:\n\t"
218         "mov %%l3, %%sp\n\t"        // readjust stack so that our locals are where they belong
219         "st %%o0, %0\n\t"           // save possible return registers into our locals
220         "st %%o1, %1\n\t"
221         "std %%f0, %2\n\t"
222         "st %%f0, %3\n\t"
223 
224         // restore registers
225         "ldd [%%l7], %%l0\n\t"
226         "add %%l7, 8, %%l7\n\t"
227         "ldd [%%l7], %%l2\n\t"
228         "add %%l7, 8, %%l7\n\t"
229         "ldd [%%l7], %%l4\n\t"
230         "add %%l7, 8, %%l7\n\t"
231         "ldd [%%l7], %%o0\n\t"
232         "add %%l7, 8, %%l7\n\t"
233         "ldd [%%l7], %%o2\n\t"
234         "add %%l7, 8, %%l7\n\t"
235         "ldd [%%l7], %%o4\n\t"
236         "add %%l7, 8, %%l7\n\t"
237         "ldd [%%l7], %%l6\n\t"
238         : :
239         "m"(o0),
240         "m"(o1),
241         "m"(f0d),
242         "m"(f0f),
243         "r"(&saveReg[0])
244         );
245     switch( eReturnType )
246     {
247         case typelib_TypeClass_HYPER:
248         case typelib_TypeClass_UNSIGNED_HYPER:
249             ((long*)pRegisterReturn)[1] = o1;
250         case typelib_TypeClass_LONG:
251         case typelib_TypeClass_UNSIGNED_LONG:
252         case typelib_TypeClass_ENUM:
253             ((long*)pRegisterReturn)[0] = o0;
254             break;
255         case typelib_TypeClass_CHAR:
256         case typelib_TypeClass_SHORT:
257         case typelib_TypeClass_UNSIGNED_SHORT:
258             *(unsigned short*)pRegisterReturn = (unsigned short)o0;
259             break;
260         case typelib_TypeClass_BOOLEAN:
261         case typelib_TypeClass_BYTE:
262             *(unsigned char*)pRegisterReturn = (unsigned char)o0;
263             break;
264         case typelib_TypeClass_FLOAT:
265             *(float*)pRegisterReturn = f0f;
266             break;
267         case typelib_TypeClass_DOUBLE:
268             *(double*)pRegisterReturn = f0d;
269             break;
270     }
271 }
272 
273 //=================================================================================================
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)274 static void cpp_call(
275     bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
276     bridges::cpp_uno::shared::VtableSlot aVtableSlot,
277     typelib_TypeDescriptionReference * pReturnTypeRef,
278     sal_Int32 nParams, typelib_MethodParameter * pParams,
279     void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc )
280 {
281     // max space for: complex ret ptr, this, values|ptr ...
282     char * pCppStack    =
283         (char *)alloca( (nParams+2) * sizeof(sal_Int64) );
284     char * pCppStackStart   = pCppStack;
285 
286     // return
287     typelib_TypeDescription * pReturnTypeDescr = 0;
288     TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
289     OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" );
290 
291     void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
292 
293     if (pReturnTypeDescr)
294     {
295         if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
296         {
297             pCppReturn = pUnoReturn; // direct way for simple types
298             *(void**)pCppStack = NULL;
299         }
300         else
301         {
302             // complex return via ptr
303             pCppReturn = *(void **)pCppStack = (bridges::cpp_uno::shared::relatesToInterfaceType(pReturnTypeDescr )
304                                                 ? alloca( pReturnTypeDescr->nSize )
305                                                 : pUnoReturn); // direct way
306         }
307         pCppStack += sizeof(void*);
308     }
309     // push this
310     void * pAdjustedThisPtr = reinterpret_cast< void ** >(pThis->getCppI())
311            + aVtableSlot.offset;
312            *(void**)pCppStack = pAdjustedThisPtr;
313     pCppStack += sizeof( void* );
314 
315     // stack space
316     OSL_ENSURE( sizeof(void *) == sizeof(sal_Int32), "### unexpected size!" );
317     // args
318     void ** pCppArgs  = (void **)alloca( 3 * sizeof(void *) * nParams );
319     // indizes of values this have to be converted (interface conversion cpp<=>uno)
320     sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams);
321     // type descriptions for reconversions
322     typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
323 
324     sal_Int32 nTempIndizes   = 0;
325 
326     for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
327     {
328         const typelib_MethodParameter & rParam = pParams[nPos];
329         typelib_TypeDescription * pParamTypeDescr = 0;
330         TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
331         if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
332         {
333             pCppArgs[ nPos ] = CPPU_CURRENT_NAMESPACE::adjustPointer(pCppStack, pParamTypeDescr );
334 
335             switch (pParamTypeDescr->eTypeClass)
336             {
337             case typelib_TypeClass_HYPER:
338             case typelib_TypeClass_UNSIGNED_HYPER:
339             case typelib_TypeClass_DOUBLE:
340                         OSL_ASSERT( sizeof (double) == sizeof (sal_Int64) );
341                           *reinterpret_cast< sal_Int32 * >(pCppStack) =
342                           *reinterpret_cast< sal_Int32 const * >(pUnoArgs[ nPos ]);
343                           pCppStack += sizeof (sal_Int32);
344                           *reinterpret_cast< sal_Int32 * >(pCppStack) =
345                           *(reinterpret_cast< sal_Int32 const * >(pUnoArgs[ nPos ] ) + 1);
346                           break;
347                     default:
348                           uno_copyAndConvertData(
349                              pCppArgs[nPos], pUnoArgs[nPos], pParamTypeDescr,
350                             pThis->getBridge()->getUno2Cpp() );
351                           break;
352                         }
353             // no longer needed
354             TYPELIB_DANGER_RELEASE( pParamTypeDescr );
355         }
356         else // ptr to complex value | ref
357         {
358             if (! rParam.bIn) // is pure out
359             {
360                 // cpp out is constructed mem, uno out is not!
361                 uno_constructData(
362                     *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
363                     pParamTypeDescr );
364                 pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call
365                 // will be released at reconversion
366                 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
367             }
368             // is in/inout
369             else if (bridges::cpp_uno::shared::relatesToInterfaceType(
370                             pParamTypeDescr ))
371             {
372                 uno_copyAndConvertData(
373                     *(void **)pCppStack = pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
374                                     pUnoArgs[nPos], pParamTypeDescr,
375                     pThis->getBridge()->getUno2Cpp() );
376 
377                 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
378                 // will be released at reconversion
379                 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
380             }
381             else // direct way
382             {
383                 *(void **)pCppStack = pCppArgs[nPos] = pUnoArgs[nPos];
384                 // no longer needed
385                 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
386             }
387         }
388         pCppStack += sizeof(sal_Int32); // standard parameter length
389     }
390 
391     try
392     {
393         int nStackLongs = (pCppStack - pCppStackStart)/sizeof(sal_Int32);
394         OSL_ENSURE( !( (pCppStack - pCppStackStart ) & 3), "UNALIGNED STACK !!! (Please DO panic" );
395 
396         if( nStackLongs & 1 )
397             // stack has to be 8 byte aligned
398             nStackLongs++;
399         callVirtualMethod(
400             pAdjustedThisPtr,
401             aVtableSlot.index,
402             pCppReturn,
403             pReturnTypeDescr->eTypeClass,
404             (sal_Int32 *)pCppStackStart,
405              nStackLongs);
406         // NO exception occured...
407         *ppUnoExc = 0;
408 
409         // reconvert temporary params
410         for ( ; nTempIndizes--; )
411         {
412             sal_Int32 nIndex = pTempIndizes[nTempIndizes];
413             typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
414 
415             if (pParams[nIndex].bIn)
416             {
417                 if (pParams[nIndex].bOut) // inout
418                 {
419                     uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value
420                     uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
421                                             pThis->getBridge()->getCpp2Uno() );
422                 }
423             }
424             else // pure out
425             {
426                 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
427                                         pThis->getBridge()->getCpp2Uno() );
428             }
429             // destroy temp cpp param => cpp: every param was constructed
430             uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
431 
432             TYPELIB_DANGER_RELEASE( pParamTypeDescr );
433         }
434         // return value
435         if (pCppReturn && pUnoReturn != pCppReturn)
436         {
437             uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
438                                     pThis->getBridge()->getCpp2Uno() );
439             uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release );
440         }
441     }
442     catch( ... )
443     {
444         // get exception
445            fillUnoException( CPPU_CURRENT_NAMESPACE::__cxa_get_globals()->caughtExceptions,
446                                 *ppUnoExc, pThis->getBridge()->getCpp2Uno() );
447 
448         // temporary params
449         for ( ; nTempIndizes--; )
450         {
451             sal_Int32 nIndex = pTempIndizes[nTempIndizes];
452             // destroy temp cpp param => cpp: every param was constructed
453             uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release );
454             TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
455         }
456         // return type
457         if (pReturnTypeDescr)
458             TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
459     }
460 }
461 
462 }
463 
464 namespace bridges { namespace cpp_uno { namespace shared {
465 
unoInterfaceProxyDispatch(uno_Interface * pUnoI,const typelib_TypeDescription * pMemberDescr,void * pReturn,void * pArgs[],uno_Any ** ppException)466 void unoInterfaceProxyDispatch(
467     uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
468     void * pReturn, void * pArgs[], uno_Any ** ppException )
469 {
470 #if defined BRIDGES_DEBUG
471     OString cstr( OUStringToOString( pMemberDescr->pTypeName, RTL_TEXTENCODING_ASCII_US ) );
472     fprintf( stderr, "received dispatch( %s )\n", cstr.getStr() );
473 #endif
474 
475     // is my surrogate
476     bridges::cpp_uno::shared::UnoInterfaceProxy * pThis
477        = static_cast< bridges::cpp_uno::shared::UnoInterfaceProxy * >(pUnoI);
478     typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
479 
480     switch (pMemberDescr->eTypeClass)
481     {
482     case typelib_TypeClass_INTERFACE_ATTRIBUTE:
483     {
484      VtableSlot aVtableSlot(
485                getVtableSlot(
486                    reinterpret_cast<
487                        typelib_InterfaceAttributeTypeDescription const * >(
488                            pMemberDescr)));
489         if (pReturn)
490         {
491             // dependent dispatch
492             cpp_call(
493                 pThis, aVtableSlot,
494                 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
495                 0, 0, // no params
496                 pReturn, pArgs, ppException );
497         }
498         else
499         {
500             // is SET
501             typelib_MethodParameter aParam;
502             aParam.pTypeRef =
503                 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
504             aParam.bIn      = sal_True;
505             aParam.bOut     = sal_False;
506 
507             typelib_TypeDescriptionReference * pReturnTypeRef = 0;
508             OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") );
509             typelib_typedescriptionreference_new(
510                 &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
511 
512             // dependent dispatch
513             aVtableSlot.index += 1; // get, then set method
514             cpp_call(
515                 pThis, aVtableSlot,
516                 pReturnTypeRef,
517                 1, &aParam,
518                 pReturn, pArgs, ppException );
519 
520             typelib_typedescriptionreference_release( pReturnTypeRef );
521         }
522 
523         break;
524     }
525     case typelib_TypeClass_INTERFACE_METHOD:
526     {
527         VtableSlot aVtableSlot(
528         getVtableSlot(
529          reinterpret_cast<
530           typelib_InterfaceMethodTypeDescription const * >(
531           pMemberDescr)));
532         switch (aVtableSlot.index)
533         {
534             // standard calls
535         case 1: // acquire uno interface
536             (*pUnoI->acquire)( pUnoI );
537             *ppException = 0;
538             break;
539         case 2: // release uno interface
540             (*pUnoI->release)( pUnoI );
541             *ppException = 0;
542             break;
543         case 0: // queryInterface() opt
544         {
545             typelib_TypeDescription * pTD = 0;
546             TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
547             if (pTD)
548             {
549                 uno_Interface * pInterface = 0;
550         (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)(
551           pThis->pBridge->getUnoEnv(),
552                    (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
553 
554                 if (pInterface)
555                 {
556                     ::uno_any_construct(
557                         reinterpret_cast< uno_Any * >( pReturn ),
558                         &pInterface, pTD, 0 );
559                     (*pInterface->release)( pInterface );
560                     TYPELIB_DANGER_RELEASE( pTD );
561                     *ppException = 0;
562                     break;
563                 }
564                 TYPELIB_DANGER_RELEASE( pTD );
565             }
566         } // else perform queryInterface()
567         default:
568             // dependent dispatch
569             cpp_call(
570                 pThis, aVtableSlot,
571                 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
572                 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
573                 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
574                 pReturn, pArgs, ppException );
575         }
576         break;
577     }
578     default:
579     {
580         ::com::sun::star::uno::RuntimeException aExc(
581             OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ),
582             ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
583 
584         Type const & rExcType = ::getCppuType( &aExc );
585         // binary identical null reference
586         ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
587     }
588     }
589 }
590 
591 } } }
592