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