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