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 <stdlib.h>
28
29 #include <exception>
30 #include <malloc.h>
31 #include <typeinfo>
32
33 #include <com/sun/star/uno/Exception.hpp>
34 #include <com/sun/star/uno/RuntimeException.hpp>
35 #include <com/sun/star/uno/genfunc.hxx>
36 #include <uno/data.h>
37
38 #include "bridges/cpp_uno/shared/bridge.hxx"
39 #include "bridges/cpp_uno/shared/types.hxx"
40 #include "bridges/cpp_uno/shared/unointerfaceproxy.hxx"
41 #include "bridges/cpp_uno/shared/vtables.hxx"
42
43 #include "share.hxx"
44
45 #include <stdio.h>
46 #include <string.h>
47
48
49 using namespace ::rtl;
50 using namespace ::com::sun::star::uno;
51 #ifdef __GLIBCXX__
52 using CPPU_CURRENT_NAMESPACE::__cxa_exception;
53 using CPPU_CURRENT_NAMESPACE::__cxa_get_globals;
54 #else
55 using __cxxabiv1::__cxa_exception;
56 using __cxxabiv1::__cxa_current_primary_exception;
57 using __cxxabiv1::__cxa_decrement_exception_refcount;
58 #endif
59
60 namespace ppc64
61 {
62 #if defined(_CALL_ELF) && _CALL_ELF == 2
is_complex_struct(const typelib_TypeDescription * type)63 bool is_complex_struct(const typelib_TypeDescription * type)
64 {
65 const typelib_CompoundTypeDescription * p
66 = reinterpret_cast< const typelib_CompoundTypeDescription * >(type);
67 for (sal_Int32 i = 0; i < p->nMembers; ++i)
68 {
69 if (p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_STRUCT ||
70 p->ppTypeRefs[i]->eTypeClass == typelib_TypeClass_EXCEPTION)
71 {
72 typelib_TypeDescription * t = 0;
73 TYPELIB_DANGER_GET(&t, p->ppTypeRefs[i]);
74 bool b = is_complex_struct(t);
75 TYPELIB_DANGER_RELEASE(t);
76 if (b) {
77 return true;
78 }
79 }
80 else if (!bridges::cpp_uno::shared::isSimpleType(p->ppTypeRefs[i]->eTypeClass))
81 return true;
82 }
83 if (p->pBaseTypeDescription != 0)
84 return is_complex_struct(&p->pBaseTypeDescription->aBase);
85 return false;
86 }
87 #endif
88
return_in_hidden_param(typelib_TypeDescriptionReference * pTypeRef)89 bool return_in_hidden_param( typelib_TypeDescriptionReference *pTypeRef )
90 {
91 if (bridges::cpp_uno::shared::isSimpleType(pTypeRef))
92 return false;
93 #if defined(_CALL_ELF) && _CALL_ELF == 2
94 else if (pTypeRef->eTypeClass == typelib_TypeClass_STRUCT || pTypeRef->eTypeClass == typelib_TypeClass_EXCEPTION)
95 {
96 typelib_TypeDescription * pTypeDescr = 0;
97 TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
98
99 //A Composite Type not larger than 16 bytes is returned in up to two GPRs
100 bool bRet = pTypeDescr->nSize > 16 || is_complex_struct(pTypeDescr);
101
102 TYPELIB_DANGER_RELEASE( pTypeDescr );
103 return bRet;
104 }
105 #endif
106 return true;
107 }
108 }
109
MapReturn(long r3,long r4,double dret,typelib_TypeDescriptionReference * pReturnType,void * pRegisterReturn)110 extern "C" void MapReturn(long r3, long r4, double dret, typelib_TypeDescriptionReference* pReturnType, void *pRegisterReturn)
111 {
112 switch (pReturnType->eTypeClass)
113 {
114 case typelib_TypeClass_HYPER:
115 case typelib_TypeClass_UNSIGNED_HYPER:
116 *reinterpret_cast<sal_uInt64 *>( pRegisterReturn ) = r3;
117 break;
118 case typelib_TypeClass_LONG:
119 case typelib_TypeClass_UNSIGNED_LONG:
120 case typelib_TypeClass_ENUM:
121 *reinterpret_cast<sal_uInt32 *>( pRegisterReturn ) = r3;
122 break;
123 case typelib_TypeClass_CHAR:
124 case typelib_TypeClass_SHORT:
125 case typelib_TypeClass_UNSIGNED_SHORT:
126 *reinterpret_cast<sal_uInt16 *>( pRegisterReturn ) = (unsigned short)r3;
127 break;
128 case typelib_TypeClass_BOOLEAN:
129 case typelib_TypeClass_BYTE:
130 *reinterpret_cast<sal_uInt8 *>( pRegisterReturn ) = (unsigned char)r3;
131 break;
132 case typelib_TypeClass_FLOAT:
133 *reinterpret_cast<float *>( pRegisterReturn ) = dret;
134 break;
135 case typelib_TypeClass_DOUBLE:
136 *reinterpret_cast<double *>( pRegisterReturn ) = dret;
137 break;
138 #if defined(_CALL_ELF) && _CALL_ELF == 2
139 case typelib_TypeClass_STRUCT:
140 case typelib_TypeClass_EXCEPTION:
141 if (!ppc64::return_in_hidden_param(pReturnType))
142 {
143 sal_uInt64 *pRegisters = reinterpret_cast<sal_uInt64*>(pRegisterReturn);
144 pRegisters[0] = r3;
145 if (pReturnType->pType->nSize > 8)
146 pRegisters[1] = r4;
147 }
148 #else
149 (void)r4;
150 #endif
151 default:
152 break;
153 }
154 }
155
156 namespace
157 {
158 //==================================================================================================
159 extern "C" void callVirtualMethod(void * pThis, sal_uInt32 nVtableIndex,
160 void * pRegisterReturn, typelib_TypeDescription * pReturnTypeDescr,
161 sal_uInt64 *pStack, sal_uInt32 nStack,
162 sal_uInt64 *pGPR, sal_uInt32 nGPR,
163 double *pFPR, sal_uInt32 nFPR);
164
165 #if 0
166 {
167 // Stack, if used, must be 16-bytes aligned
168 if ( nStack )
169 nStack = ( nStack + 1 ) & ~1;
170
171 // Should not happen, but...
172 if ( nFPR > ppc64::MAX_SSE_REGS )
173 nFPR = ppc64::MAX_SSE_REGS;
174 if ( nGPR > ppc64::MAX_GPR_REGS )
175 nGPR = ppc64::MAX_GPR_REGS;
176
177 #ifdef CMC_DEBUG
178 // Let's figure out what is really going on here
179 {
180 fprintf( stderr, "= callVirtualMethod() =\nGPR's (%d): ", nGPR );
181 for ( sal_uInt32 i = 0; i < nGPR; ++i )
182 fprintf( stderr, "0x%lx, ", pGPR[i] );
183 fprintf( stderr, "\nFPR's (%d): ", nFPR );
184 for ( sal_uInt32 i = 0; i < nFPR; ++i )
185 fprintf( stderr, "0x%lx (%lf), ", (sal_Int64)pFPR[i], pFPR[i] );
186 fprintf( stderr, "\nStack (%d): ", nStack );
187 for ( sal_uInt32 i = 0; i < nStack; ++i )
188 fprintf( stderr, "0x%lx, ", pStack[i] );
189 fprintf( stderr, "\n" );
190 }
191 #endif
192
193 // Load parameters to stack, if necessary
194 sal_uInt64 *stack = (sal_uInt64 *) __builtin_alloca( nStack * 8 );
195 memcpy( stack, pStack, nStack * 8 );
196
197 // Get pointer to method
198 sal_uInt64 pMethod = *((sal_uInt64 *)pThis);
199 pMethod += 8 * nVtableIndex;
200 pMethod = *((sal_uInt64 *)pMethod);
201
202 #if defined(_CALL_ELF) && _CALL_ELF == 2
203 typedef void (* FunctionCall )(...);
204 #else
205 typedef void (* FunctionCall )( sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64, sal_uInt64 );
206 #endif
207 FunctionCall pFunc = (FunctionCall)pMethod;
208
209 volatile double dret;
210
211 // fill registers
212 __asm__ __volatile__ (
213 "lfd 1, 0(%0)\n\t"
214 "lfd 2, 8(%0)\n\t"
215 "lfd 3, 16(%0)\n\t"
216 "lfd 4, 24(%0)\n\t"
217 "lfd 5, 32(%0)\n\t"
218 "lfd 6, 40(%0)\n\t"
219 "lfd 7, 48(%0)\n\t"
220 "lfd 8, 56(%0)\n\t"
221 "lfd 9, 64(%0)\n\t"
222 "lfd 10, 72(%0)\n\t"
223 "lfd 11, 80(%0)\n\t"
224 "lfd 12, 88(%0)\n\t"
225 "lfd 13, 96(%0)\n\t"
226 : : "r" (pFPR)
227 : "fr1", "fr2", "fr3", "fr4", "fr5", "fr6", "fr7", "fr8", "fr9",
228 "fr10", "fr11", "fr12", "fr13"
229 );
230
231 // tell gcc that r3 to r11 are not available to it for doing the TOC and exception munge on the func call
232 register sal_uInt64 r3 asm("r3");
233 register sal_uInt64 r4 asm("r4");
234
235 (*pFunc)(pGPR[0], pGPR[1], pGPR[2], pGPR[3], pGPR[4], pGPR[5], pGPR[6], pGPR[7]);
236
237 // get return value
238 __asm__ __volatile__ (
239 "mr %1, 3\n\t"
240 "mr %2, 4\n\t"
241 "fmr %0, 1\n\t"
242 : "=f" (dret), "=r" (r3), "=r" (r4) : );
243
244 MapReturn(r3, r4, dret, reinterpret_cast<typelib_TypeDescriptionReference *>(pReturnTypeDescr), pRegisterReturn);
245 }
246 #endif
247
248 // Macros for easier insertion of values to registers or stack
249 // pSV - pointer to the source
250 // nr - order of the value [will be increased if stored to register]
251 // pFPR, pGPR - pointer to the registers
252 // pDS - pointer to the stack [will be increased if stored here]
253
254 // The value in %xmm register is already prepared to be retrieved as a float,
255 // thus we treat float and double the same
256 #define INSERT_FLOAT( pSV, nr, pFPR, nGPR, pDS, bOverFlow ) \
257 if ( nGPR < ppc64::MAX_GPR_REGS ) \
258 ++nGPR; \
259 if ( nr < ppc64::MAX_SSE_REGS ) \
260 pFPR[nr++] = *reinterpret_cast<float *>( pSV ); \
261 else \
262 bOverFlow = true; \
263 if (bOverFlow) \
264 *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); // verbatim!
265
266 #define INSERT_DOUBLE( pSV, nr, pFPR, nGPR, pDS, bOverFlow ) \
267 if ( nGPR < ppc64::MAX_GPR_REGS ) \
268 ++nGPR; \
269 if ( nr < ppc64::MAX_SSE_REGS ) \
270 pFPR[nr++] = *reinterpret_cast<double *>( pSV ); \
271 else \
272 bOverFlow = true; \
273 if (bOverFlow) \
274 *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV ); // verbatim!
275
276 #define INSERT_INT64( pSV, nr, pGPR, pDS, bOverFlow ) \
277 if ( nr < ppc64::MAX_GPR_REGS ) \
278 pGPR[nr++] = *reinterpret_cast<sal_Int64 *>( pSV ); \
279 else \
280 bOverFlow = true; \
281 if (bOverFlow) \
282 *pDS++ = *reinterpret_cast<sal_Int64 *>( pSV );
283
284 #define INSERT_UINT64( pSV, nr, pGPR, pDS, bOverFlow ) \
285 if ( nr < ppc64::MAX_GPR_REGS ) \
286 pGPR[nr++] = *reinterpret_cast<sal_uInt64 *>( pSV ); \
287 else \
288 bOverFlow = true; \
289 if (bOverFlow) \
290 *pDS++ = *reinterpret_cast<sal_uInt64 *>( pSV );
291
292 #define INSERT_INT32( pSV, nr, pGPR, pDS, bOverFlow ) \
293 if ( nr < ppc64::MAX_GPR_REGS ) \
294 pGPR[nr++] = *reinterpret_cast<sal_Int32 *>( pSV ); \
295 else \
296 bOverFlow = true; \
297 if (bOverFlow) \
298 *pDS++ = *reinterpret_cast<sal_Int32 *>( pSV );
299
300 #define INSERT_UINT32( pSV, nr, pGPR, pDS, bOverFlow ) \
301 if ( nr < ppc64::MAX_GPR_REGS ) \
302 pGPR[nr++] = *reinterpret_cast<sal_uInt32 *>( pSV ); \
303 else \
304 bOverFlow = true; \
305 if (bOverFlow) \
306 *pDS++ = *reinterpret_cast<sal_uInt32 *>( pSV );
307
308 #define INSERT_INT16( pSV, nr, pGPR, pDS, bOverFlow ) \
309 if ( nr < ppc64::MAX_GPR_REGS ) \
310 pGPR[nr++] = *reinterpret_cast<sal_Int16 *>( pSV ); \
311 else \
312 bOverFlow = true; \
313 if (bOverFlow) \
314 *pDS++ = *reinterpret_cast<sal_Int16 *>( pSV );
315
316 #define INSERT_UINT16( pSV, nr, pGPR, pDS, bOverFlow ) \
317 if ( nr < ppc64::MAX_GPR_REGS ) \
318 pGPR[nr++] = *reinterpret_cast<sal_uInt16 *>( pSV ); \
319 else \
320 bOverFlow = true; \
321 if (bOverFlow) \
322 *pDS++ = *reinterpret_cast<sal_uInt16 *>( pSV );
323
324 #define INSERT_INT8( pSV, nr, pGPR, pDS, bOverFlow ) \
325 if ( nr < ppc64::MAX_GPR_REGS ) \
326 pGPR[nr++] = *reinterpret_cast<sal_Int8 *>( pSV ); \
327 else \
328 bOverFlow = true; \
329 if (bOverFlow) \
330 *pDS++ = *reinterpret_cast<sal_Int8 *>( pSV );
331
332 #define INSERT_UINT8( pSV, nr, pGPR, pDS, bOverFlow ) \
333 if ( nr < ppc64::MAX_GPR_REGS ) \
334 pGPR[nr++] = *reinterpret_cast<sal_uInt8 *>( pSV ); \
335 else \
336 bOverFlow = true; \
337 if (bOverFlow) \
338 *pDS++ = *reinterpret_cast<sal_uInt8 *>( pSV );
339
340 //==================================================================================================
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)341 static void cpp_call(
342 bridges::cpp_uno::shared::UnoInterfaceProxy * pThis,
343 bridges::cpp_uno::shared::VtableSlot aVtableSlot,
344 typelib_TypeDescriptionReference * pReturnTypeRef,
345 sal_Int32 nParams, typelib_MethodParameter * pParams,
346 void * pUnoReturn, void * pUnoArgs[], uno_Any ** ppUnoExc )
347 {
348 // max space for: [complex ret ptr], values|ptr ...
349 sal_uInt64 * pStack = (sal_uInt64 *)alloca( (nParams+3) * sizeof(sal_Int64) );
350 sal_uInt64 * pStackStart = pStack;
351
352 sal_uInt64 pGPR[ppc64::MAX_GPR_REGS];
353 sal_uInt32 nGPR = 0;
354
355 double pFPR[ppc64::MAX_SSE_REGS];
356 sal_uInt32 nFPR = 0;
357
358 // return
359 typelib_TypeDescription * pReturnTypeDescr = 0;
360 TYPELIB_DANGER_GET( &pReturnTypeDescr, pReturnTypeRef );
361 OSL_ENSURE( pReturnTypeDescr, "### expected return type description!" );
362
363 void * pCppReturn = 0; // if != 0 && != pUnoReturn, needs reconversion
364
365 bool bOverFlow = false;
366
367 if (pReturnTypeDescr)
368 {
369 #ifdef CMC_DEBUG
370 fprintf(stderr, "return type is %d\n", pReturnTypeDescr->eTypeClass);
371 #endif
372 if (bridges::cpp_uno::shared::isSimpleType( pReturnTypeDescr ))
373 {
374 pCppReturn = pUnoReturn; // direct way for simple types
375 #ifdef CMC_DEBUG
376 fprintf(stderr, "simple return\n");
377 #endif
378 }
379 else
380 {
381 // complex return via ptr
382 pCppReturn = (bridges::cpp_uno::shared::relatesToInterfaceType( pReturnTypeDescr )
383 ? alloca( pReturnTypeDescr->nSize ) : pUnoReturn);
384 #ifdef CMC_DEBUG
385 fprintf(stderr, "pCppReturn/pUnoReturn is %lx/%lx", pCppReturn, pUnoReturn);
386 #endif
387 INSERT_INT64( &pCppReturn, nGPR, pGPR, pStack, bOverFlow );
388 }
389 }
390 // push "this" pointer
391 void * pAdjustedThisPtr = reinterpret_cast< void ** >( pThis->getCppI() ) + aVtableSlot.offset;
392 #ifdef CMC_DEBUG
393 fprintf(stderr, "this pointer is %p\n", pAdjustedThisPtr);
394 #endif
395 INSERT_INT64( &pAdjustedThisPtr, nGPR, pGPR, pStack, bOverFlow );
396
397 // Args
398 void ** pCppArgs = (void **)alloca( 3 * sizeof(void *) * nParams );
399 // indizes of values this have to be converted (interface conversion cpp<=>uno)
400 sal_Int32 * pTempIndizes = (sal_Int32 *)(pCppArgs + nParams);
401 // type descriptions for reconversions
402 typelib_TypeDescription ** ppTempParamTypeDescr = (typelib_TypeDescription **)(pCppArgs + (2 * nParams));
403
404 sal_Int32 nTempIndizes = 0;
405
406 #ifdef CMC_DEBUG
407 fprintf(stderr, "n params is %d\n", nParams);
408 #endif
409
410 for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos )
411 {
412 const typelib_MethodParameter & rParam = pParams[nPos];
413 typelib_TypeDescription * pParamTypeDescr = 0;
414 TYPELIB_DANGER_GET( &pParamTypeDescr, rParam.pTypeRef );
415
416 #ifdef CMC_DEBUG
417 fprintf(stderr, "param %d is %d %d %d\n", nPos, rParam.bOut, bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ),
418 pParamTypeDescr->eTypeClass);
419 #endif
420
421 if (!rParam.bOut && bridges::cpp_uno::shared::isSimpleType( pParamTypeDescr ))
422 {
423 // uno_copyAndConvertData( pCppArgs[nPos] = alloca( 8 ), pUnoArgs[nPos], pParamTypeDescr,
424 uno_copyAndConvertData( pCppArgs[nPos] = pStack, pUnoArgs[nPos], pParamTypeDescr,
425 pThis->getBridge()->getUno2Cpp() );
426 switch (pParamTypeDescr->eTypeClass)
427 {
428 case typelib_TypeClass_HYPER:
429 case typelib_TypeClass_UNSIGNED_HYPER:
430 #ifdef CMC_DEBUG
431 fprintf(stderr, "hyper is %lx\n", pCppArgs[nPos]);
432 #endif
433 INSERT_INT64( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow );
434 break;
435 case typelib_TypeClass_LONG:
436 case typelib_TypeClass_UNSIGNED_LONG:
437 case typelib_TypeClass_ENUM:
438 #ifdef CMC_DEBUG
439 fprintf(stderr, "long is %x\n", pCppArgs[nPos]);
440 #endif
441 INSERT_INT32( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow );
442 break;
443 case typelib_TypeClass_SHORT:
444 INSERT_INT16( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow );
445 break;
446 case typelib_TypeClass_CHAR:
447 case typelib_TypeClass_UNSIGNED_SHORT:
448 INSERT_INT16( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow );
449 break;
450 case typelib_TypeClass_BOOLEAN:
451 INSERT_UINT8( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow );
452 break;
453 case typelib_TypeClass_BYTE:
454 INSERT_INT8( pCppArgs[nPos], nGPR, pGPR, pStack, bOverFlow );
455 break;
456 case typelib_TypeClass_FLOAT:
457 INSERT_FLOAT( pCppArgs[nPos], nFPR, pFPR, nGPR, pStack, bOverFlow );
458 break;
459 case typelib_TypeClass_DOUBLE:
460 INSERT_DOUBLE( pCppArgs[nPos], nFPR, pFPR, nGPR, pStack, bOverFlow );
461 break;
462 }
463
464 // no longer needed
465 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
466
467 }
468 else // ptr to complex value | ref
469 {
470 #ifdef CMC_DEBUG
471 fprintf(stderr, "complex type again %d\n", rParam.bIn);
472 #endif
473 if (! rParam.bIn) // is pure out
474 {
475 #ifdef CMC_DEBUG
476 fprintf(stderr, "complex size is %d\n", pParamTypeDescr->nSize );
477 #endif
478 // cpp out is constructed mem, uno out is not!
479 uno_constructData(
480 pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
481 pParamTypeDescr );
482 pTempIndizes[nTempIndizes] = nPos; // default constructed for cpp call
483 // will be released at reconversion
484 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
485 }
486 // is in/inout
487 else if (bridges::cpp_uno::shared::relatesToInterfaceType( pParamTypeDescr ))
488 {
489 #ifdef CMC_DEBUG
490 fprintf(stderr, "this one\n");
491 #endif
492 uno_copyAndConvertData(
493 pCppArgs[nPos] = alloca( pParamTypeDescr->nSize ),
494 pUnoArgs[nPos], pParamTypeDescr, pThis->getBridge()->getUno2Cpp() );
495
496 pTempIndizes[nTempIndizes] = nPos; // has to be reconverted
497 // will be released at reconversion
498 ppTempParamTypeDescr[nTempIndizes++] = pParamTypeDescr;
499 }
500 else // direct way
501 {
502 #ifdef CMC_DEBUG
503 fprintf(stderr, "that one, passing %lx through\n", pUnoArgs[nPos]);
504 #endif
505 pCppArgs[nPos] = pUnoArgs[nPos];
506 // no longer needed
507 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
508 }
509 INSERT_INT64( &(pCppArgs[nPos]), nGPR, pGPR, pStack, bOverFlow );
510 }
511 }
512
513 try
514 {
515 callVirtualMethod(
516 pAdjustedThisPtr, aVtableSlot.index,
517 pCppReturn, pReturnTypeDescr,
518 pStackStart, ( pStack - pStackStart ),
519 pGPR, nGPR,
520 pFPR, nFPR );
521 // NO exception occurred...
522 *ppUnoExc = 0;
523
524 // reconvert temporary params
525 for ( ; nTempIndizes--; )
526 {
527 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
528 typelib_TypeDescription * pParamTypeDescr = ppTempParamTypeDescr[nTempIndizes];
529
530 if (pParams[nIndex].bIn)
531 {
532 if (pParams[nIndex].bOut) // inout
533 {
534 uno_destructData( pUnoArgs[nIndex], pParamTypeDescr, 0 ); // destroy uno value
535 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
536 pThis->getBridge()->getCpp2Uno() );
537 }
538 }
539 else // pure out
540 {
541 uno_copyAndConvertData( pUnoArgs[nIndex], pCppArgs[nIndex], pParamTypeDescr,
542 pThis->getBridge()->getCpp2Uno() );
543 }
544 // destroy temp cpp param => cpp: every param was constructed
545 uno_destructData( pCppArgs[nIndex], pParamTypeDescr, cpp_release );
546
547 TYPELIB_DANGER_RELEASE( pParamTypeDescr );
548 }
549 // return value
550 if (pCppReturn && pUnoReturn != pCppReturn)
551 {
552 uno_copyAndConvertData( pUnoReturn, pCppReturn, pReturnTypeDescr,
553 pThis->getBridge()->getCpp2Uno() );
554 uno_destructData( pCppReturn, pReturnTypeDescr, cpp_release );
555 }
556 }
557 catch (...)
558 {
559 __cxa_exception *header;
560 #ifdef __GLIBCXX__
561 header = __cxa_get_globals()->caughtExceptions;
562 #else
563 header = reinterpret_cast<__cxa_exception *>( __cxa_current_primary_exception() );
564 if (header) {
565 __cxa_decrement_exception_refcount( header );
566 header--;
567 }
568 #endif
569 // fill uno exception
570 CPPU_CURRENT_NAMESPACE::fillUnoException( header, *ppUnoExc, pThis->getBridge()->getCpp2Uno() );
571
572 // temporary params
573 for ( ; nTempIndizes--; )
574 {
575 sal_Int32 nIndex = pTempIndizes[nTempIndizes];
576 // destroy temp cpp param => cpp: every param was constructed
577 uno_destructData( pCppArgs[nIndex], ppTempParamTypeDescr[nTempIndizes], cpp_release );
578 TYPELIB_DANGER_RELEASE( ppTempParamTypeDescr[nTempIndizes] );
579 }
580 // return type
581 if (pReturnTypeDescr)
582 TYPELIB_DANGER_RELEASE( pReturnTypeDescr );
583 }
584 }
585
586 }
587
588 namespace bridges { namespace cpp_uno { namespace shared {
589
unoInterfaceProxyDispatch(uno_Interface * pUnoI,const typelib_TypeDescription * pMemberDescr,void * pReturn,void * pArgs[],uno_Any ** ppException)590 void unoInterfaceProxyDispatch(
591 uno_Interface * pUnoI, const typelib_TypeDescription * pMemberDescr,
592 void * pReturn, void * pArgs[], uno_Any ** ppException )
593 {
594 // is my surrogate
595 ::bridges::cpp_uno::shared::UnoInterfaceProxy * pThis
596 = static_cast< ::bridges::cpp_uno::shared::UnoInterfaceProxy *> (pUnoI);
597 typelib_InterfaceTypeDescription * pTypeDescr = pThis->pTypeDescr;
598
599 switch (pMemberDescr->eTypeClass)
600 {
601 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
602 {
603
604 ::bridges::cpp_uno::shared::VtableSlot aVtableSlot(
605 ::bridges::cpp_uno::shared::getVtableSlot(
606 reinterpret_cast<
607 typelib_InterfaceAttributeTypeDescription const * >(
608 pMemberDescr)));
609
610 if (pReturn)
611 {
612 // dependent dispatch
613 cpp_call(
614 pThis, aVtableSlot,
615 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef,
616 0, 0, // no params
617 pReturn, pArgs, ppException );
618 }
619 else
620 {
621 // is SET
622 typelib_MethodParameter aParam;
623 aParam.pTypeRef =
624 ((typelib_InterfaceAttributeTypeDescription *)pMemberDescr)->pAttributeTypeRef;
625 aParam.bIn = sal_True;
626 aParam.bOut = sal_False;
627
628 typelib_TypeDescriptionReference * pReturnTypeRef = 0;
629 OUString aVoidName( RTL_CONSTASCII_USTRINGPARAM("void") );
630 typelib_typedescriptionreference_new(
631 &pReturnTypeRef, typelib_TypeClass_VOID, aVoidName.pData );
632
633 // dependent dispatch
634 aVtableSlot.index += 1; //get then set method
635 cpp_call(
636 pThis, aVtableSlot,
637 pReturnTypeRef,
638 1, &aParam,
639 pReturn, pArgs, ppException );
640
641 typelib_typedescriptionreference_release( pReturnTypeRef );
642 }
643
644 break;
645 }
646 case typelib_TypeClass_INTERFACE_METHOD:
647 {
648
649 ::bridges::cpp_uno::shared::VtableSlot aVtableSlot(
650 ::bridges::cpp_uno::shared::getVtableSlot(
651 reinterpret_cast<
652 typelib_InterfaceMethodTypeDescription const * >(
653 pMemberDescr)));
654 switch (aVtableSlot.index)
655 {
656 // standard calls
657 case 1: // acquire uno interface
658 (*pUnoI->acquire)( pUnoI );
659 *ppException = 0;
660 break;
661 case 2: // release uno interface
662 (*pUnoI->release)( pUnoI );
663 *ppException = 0;
664 break;
665 case 0: // queryInterface() opt
666 {
667 typelib_TypeDescription * pTD = 0;
668 TYPELIB_DANGER_GET( &pTD, reinterpret_cast< Type * >( pArgs[0] )->getTypeLibType() );
669 if (pTD)
670 {
671 uno_Interface * pInterface = 0;
672 (*pThis->pBridge->getUnoEnv()->getRegisteredInterface)(
673 pThis->pBridge->getUnoEnv(),
674 (void **)&pInterface, pThis->oid.pData, (typelib_InterfaceTypeDescription *)pTD );
675
676 if (pInterface)
677 {
678 ::uno_any_construct(
679 reinterpret_cast< uno_Any * >( pReturn ),
680 &pInterface, pTD, 0 );
681 (*pInterface->release)( pInterface );
682 TYPELIB_DANGER_RELEASE( pTD );
683 *ppException = 0;
684 break;
685 }
686 TYPELIB_DANGER_RELEASE( pTD );
687 }
688 } // else perform queryInterface()
689 default:
690 // dependent dispatch
691 cpp_call(
692 pThis, aVtableSlot,
693 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pReturnTypeRef,
694 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->nParams,
695 ((typelib_InterfaceMethodTypeDescription *)pMemberDescr)->pParams,
696 pReturn, pArgs, ppException );
697 }
698 break;
699 }
700 default:
701 {
702 ::com::sun::star::uno::RuntimeException aExc(
703 OUString( RTL_CONSTASCII_USTRINGPARAM("illegal member type description!") ),
704 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
705
706 Type const & rExcType = ::getCppuType( &aExc );
707 // binary identical null reference
708 ::uno_type_any_construct( *ppException, &aExc, rExcType.getTypeLibType(), 0 );
709 }
710 }
711 }
712
713 } } }
714