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 #include "pyuno_impl.hxx" 29 30 #include <osl/thread.h> 31 #include <osl/module.h> 32 #include <osl/process.h> 33 #include <rtl/strbuf.hxx> 34 #include <rtl/ustrbuf.hxx> 35 #include <rtl/bootstrap.hxx> 36 #include <locale.h> 37 38 #include <typelib/typedescription.hxx> 39 40 #include <com/sun/star/beans/XMaterialHolder.hpp> 41 42 using rtl::OUString; 43 using rtl::OUStringToOString; 44 using rtl::OUStringBuffer; 45 using rtl::OStringBuffer; 46 using rtl::OString; 47 48 using com::sun::star::uno::Reference; 49 using com::sun::star::uno::XInterface; 50 using com::sun::star::uno::Any; 51 using com::sun::star::uno::TypeDescription; 52 using com::sun::star::uno::Sequence; 53 using com::sun::star::uno::Type; 54 using com::sun::star::uno::UNO_QUERY; 55 using com::sun::star::uno::RuntimeException; 56 using com::sun::star::uno::XComponentContext; 57 using com::sun::star::lang::XSingleServiceFactory; 58 using com::sun::star::lang::XUnoTunnel; 59 using com::sun::star::reflection::XIdlReflection; 60 using com::sun::star::script::XTypeConverter; 61 using com::sun::star::script::XInvocationAdapterFactory2; 62 using com::sun::star::script::XInvocation; 63 using com::sun::star::beans::XMaterialHolder; 64 using com::sun::star::beans::XIntrospection; 65 66 namespace pyuno 67 { 68 #define USTR_ASCII(x) OUString( RTL_CONSTASCII_USTRINGPARAM( x ) ) 69 70 static PyTypeObject RuntimeImpl_Type = 71 { 72 PyObject_HEAD_INIT (&PyType_Type) 73 0, 74 const_cast< char * >("pyuno_runtime"), 75 sizeof (RuntimeImpl), 76 0, 77 (destructor) RuntimeImpl::del, 78 (printfunc) 0, 79 (getattrfunc) 0, 80 (setattrfunc) 0, 81 (cmpfunc) 0, 82 (reprfunc) 0, 83 0, 84 0, 85 0, 86 (hashfunc) 0, 87 (ternaryfunc) 0, 88 (reprfunc) 0, 89 (getattrofunc)0, 90 (setattrofunc)0, 91 NULL, 92 0, 93 NULL, 94 (traverseproc)0, 95 (inquiry)0, 96 (richcmpfunc)0, 97 0, 98 (getiterfunc)0, 99 (iternextfunc)0, 100 NULL, 101 NULL, 102 NULL, 103 NULL, 104 NULL, 105 (descrgetfunc)0, 106 (descrsetfunc)0, 107 0, 108 (initproc)0, 109 (allocfunc)0, 110 (newfunc)0, 111 (freefunc)0, 112 (inquiry)0, 113 NULL, 114 NULL, 115 NULL, 116 NULL, 117 NULL, 118 (destructor)0 119 #if PY_VERSION_HEX >= 0x02060000 120 , 0 121 #endif 122 }; 123 124 /*---------------------------------------------------------------------- 125 Runtime implementation 126 -----------------------------------------------------------------------*/ 127 static void getRuntimeImpl( PyRef & globalDict, PyRef &runtimeImpl ) 128 throw ( com::sun::star::uno::RuntimeException ) 129 { 130 PyThreadState * state = PyThreadState_Get(); 131 if( ! state ) 132 { 133 throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM( 134 "python global interpreter must be held (thread must be attached)" )), 135 Reference< XInterface > () ); 136 } 137 138 globalDict = PyRef( PyModule_GetDict(PyImport_AddModule(const_cast< char * >("__main__")))); 139 140 if( ! globalDict.is() ) // FATAL ! 141 { 142 throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM( 143 "can't find __main__ module" )), Reference< XInterface > ()); 144 } 145 runtimeImpl = PyDict_GetItemString( globalDict.get() , "pyuno_runtime" ); 146 } 147 148 static PyRef importUnoModule( ) throw ( RuntimeException ) 149 { 150 PyRef globalDict = PyRef( PyModule_GetDict(PyImport_AddModule(const_cast< char * >("__main__")))); 151 // import the uno module 152 PyRef module( PyImport_ImportModule( const_cast< char * >("uno") ), SAL_NO_ACQUIRE ); 153 if( PyErr_Occurred() ) 154 { 155 PyRef excType, excValue, excTraceback; 156 PyErr_Fetch( (PyObject **)&excType, (PyObject**)&excValue,(PyObject**)&excTraceback); 157 PyRef str( PyObject_Repr( excTraceback.get() ), SAL_NO_ACQUIRE ); 158 159 OUStringBuffer buf; 160 buf.appendAscii( "python object raised an unknown exception (" ); 161 PyRef valueRep( PyObject_Repr( excValue.get() ), SAL_NO_ACQUIRE ); 162 buf.appendAscii( PyString_AsString( valueRep.get())).appendAscii( ", traceback follows\n" ); 163 buf.appendAscii( PyString_AsString( str.get() ) ); 164 throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface > () ); 165 } 166 PyRef dict( PyModule_GetDict( module.get() ) ); 167 return dict; 168 } 169 170 static void readLoggingConfig( sal_Int32 *pLevel, FILE **ppFile ) 171 { 172 *pLevel = LogLevel::NONE; 173 *ppFile = 0; 174 OUString fileName; 175 osl_getModuleURLFromFunctionAddress( 176 reinterpret_cast< oslGenericFunction >(readLoggingConfig), 177 (rtl_uString **) &fileName ); 178 fileName = OUString( fileName.getStr(), fileName.lastIndexOf( '/' )+1 ); 179 fileName += OUString::createFromAscii( SAL_CONFIGFILE("pyuno") ); 180 rtl::Bootstrap bootstrapHandle( fileName ); 181 182 OUString str; 183 if( bootstrapHandle.getFrom( USTR_ASCII( "PYUNO_LOGLEVEL" ), str ) ) 184 { 185 if( str.equalsAscii( "NONE" ) ) 186 *pLevel = LogLevel::NONE; 187 else if( str.equalsAscii( "CALL" ) ) 188 *pLevel = LogLevel::CALL; 189 else if( str.equalsAscii( "ARGS" ) ) 190 *pLevel = LogLevel::ARGS; 191 else 192 { 193 fprintf( stderr, "unknown loglevel %s\n", 194 OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() ); 195 } 196 } 197 if( *pLevel > LogLevel::NONE ) 198 { 199 *ppFile = stdout; 200 if( bootstrapHandle.getFrom( USTR_ASCII( "PYUNO_LOGTARGET" ), str ) ) 201 { 202 if( str.equalsAscii( "stdout" ) ) 203 *ppFile = stdout; 204 else if( str.equalsAscii( "stderr" ) ) 205 *ppFile = stderr; 206 else 207 { 208 oslProcessInfo data; 209 data.Size = sizeof( data ); 210 osl_getProcessInfo( 211 0 , osl_Process_IDENTIFIER , &data ); 212 osl_getSystemPathFromFileURL( str.pData, &str.pData); 213 OString o = OUStringToOString( str, osl_getThreadTextEncoding() ); 214 o += "."; 215 o += OString::valueOf( (sal_Int32)data.Ident ); 216 217 *ppFile = fopen( o.getStr() , "w" ); 218 if ( *ppFile ) 219 { 220 // do not buffer (useful if e.g. analyzing a crash) 221 setvbuf( *ppFile, 0, _IONBF, 0 ); 222 } 223 else 224 { 225 fprintf( stderr, "couldn't create file %s\n", 226 OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() ); 227 228 } 229 } 230 } 231 } 232 } 233 234 /*------------------------------------------------------------------- 235 RuntimeImpl implementations 236 *-------------------------------------------------------------------*/ 237 PyRef stRuntimeImpl::create( const Reference< XComponentContext > &ctx ) 238 throw( com::sun::star::uno::RuntimeException ) 239 { 240 RuntimeImpl *me = PyObject_New (RuntimeImpl, &RuntimeImpl_Type); 241 if( ! me ) 242 throw RuntimeException( 243 OUString( RTL_CONSTASCII_USTRINGPARAM( "cannot instantiate pyuno::RuntimeImpl" ) ), 244 Reference< XInterface > () ); 245 me->cargo = 0; 246 // must use a different struct here, as the PyObject_New 247 // makes C++ unusable 248 RuntimeCargo *c = new RuntimeCargo(); 249 readLoggingConfig( &(c->logLevel) , &(c->logFile) ); 250 log( c, LogLevel::CALL, "Instantiating pyuno bridge" ); 251 252 c->valid = 1; 253 c->xContext = ctx; 254 c->xInvocation = Reference< XSingleServiceFactory > ( 255 ctx->getServiceManager()->createInstanceWithContext( 256 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.script.Invocation" ) ), 257 ctx ), 258 UNO_QUERY ); 259 if( ! c->xInvocation.is() ) 260 throw RuntimeException( 261 OUString( RTL_CONSTASCII_USTRINGPARAM( "pyuno: couldn't instantiate invocation service" ) ), 262 Reference< XInterface > () ); 263 264 c->xTypeConverter = Reference< XTypeConverter > ( 265 ctx->getServiceManager()->createInstanceWithContext( 266 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.script.Converter" ) ), 267 ctx ), 268 UNO_QUERY ); 269 if( ! c->xTypeConverter.is() ) 270 throw RuntimeException( 271 OUString( RTL_CONSTASCII_USTRINGPARAM( "pyuno: couldn't instantiate typeconverter service" )), 272 Reference< XInterface > () ); 273 274 c->xCoreReflection = Reference< XIdlReflection > ( 275 ctx->getServiceManager()->createInstanceWithContext( 276 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.reflection.CoreReflection" ) ), 277 ctx ), 278 UNO_QUERY ); 279 if( ! c->xCoreReflection.is() ) 280 throw RuntimeException( 281 OUString( RTL_CONSTASCII_USTRINGPARAM( "pyuno: couldn't instantiate corereflection service" )), 282 Reference< XInterface > () ); 283 284 c->xAdapterFactory = Reference< XInvocationAdapterFactory2 > ( 285 ctx->getServiceManager()->createInstanceWithContext( 286 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.script.InvocationAdapterFactory" ) ), 287 ctx ), 288 UNO_QUERY ); 289 if( ! c->xAdapterFactory.is() ) 290 throw RuntimeException( 291 OUString( RTL_CONSTASCII_USTRINGPARAM( "pyuno: couldn't instantiate invocation adapter factory service" )), 292 Reference< XInterface > () ); 293 294 c->xIntrospection = Reference< XIntrospection > ( 295 ctx->getServiceManager()->createInstanceWithContext( 296 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.beans.Introspection" ) ), 297 ctx ), 298 UNO_QUERY ); 299 if( ! c->xIntrospection.is() ) 300 throw RuntimeException( 301 OUString( RTL_CONSTASCII_USTRINGPARAM( "pyuno: couldn't instantiate introspection service" )), 302 Reference< XInterface > () ); 303 304 Any a = ctx->getValueByName(OUString( 305 RTL_CONSTASCII_USTRINGPARAM("/singletons/com.sun.star.reflection.theTypeDescriptionManager" )) ); 306 a >>= c->xTdMgr; 307 if( ! c->xTdMgr.is() ) 308 throw RuntimeException( 309 OUString( RTL_CONSTASCII_USTRINGPARAM( "pyuno: couldn't retrieve typedescriptionmanager" )), 310 Reference< XInterface > () ); 311 312 me->cargo =c; 313 return PyRef( reinterpret_cast< PyObject * > ( me ), SAL_NO_ACQUIRE ); 314 } 315 316 void stRuntimeImpl::del(PyObject* self) 317 { 318 RuntimeImpl *me = reinterpret_cast< RuntimeImpl * > ( self ); 319 if( me->cargo->logFile ) 320 fclose( me->cargo->logFile ); 321 delete me->cargo; 322 PyObject_Del (self); 323 } 324 325 326 void Runtime::initialize( const Reference< XComponentContext > & ctx ) 327 throw ( RuntimeException ) 328 { 329 PyRef globalDict, runtime; 330 getRuntimeImpl( globalDict , runtime ); 331 RuntimeImpl *impl = reinterpret_cast< RuntimeImpl * > (runtime.get()); 332 333 if( runtime.is() && impl->cargo->valid ) 334 { 335 throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM( 336 "pyuno runtime has already been initialized before" ) ), 337 Reference< XInterface > () ); 338 } 339 PyRef keep( RuntimeImpl::create( ctx ) ); 340 PyDict_SetItemString( globalDict.get(), "pyuno_runtime" , keep.get() ); 341 Py_XINCREF( keep.get() ); 342 } 343 344 345 bool Runtime::isInitialized() throw ( RuntimeException ) 346 { 347 PyRef globalDict, runtime; 348 getRuntimeImpl( globalDict , runtime ); 349 RuntimeImpl *impl = reinterpret_cast< RuntimeImpl * > (runtime.get()); 350 return runtime.is() && impl->cargo->valid; 351 } 352 353 void Runtime::finalize() throw (RuntimeException) 354 { 355 PyRef globalDict, runtime; 356 getRuntimeImpl( globalDict , runtime ); 357 RuntimeImpl *impl = reinterpret_cast< RuntimeImpl * > (runtime.get()); 358 if( !runtime.is() || ! impl->cargo->valid ) 359 { 360 throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM( 361 "pyuno bridge must have been initialized before finalizing" )), 362 Reference< XInterface > () ); 363 } 364 impl->cargo->valid = false; 365 impl->cargo->xInvocation.clear(); 366 impl->cargo->xContext.clear(); 367 impl->cargo->xTypeConverter.clear(); 368 } 369 370 Runtime::Runtime() throw( RuntimeException ) 371 : impl( 0 ) 372 { 373 PyRef globalDict, runtime; 374 getRuntimeImpl( globalDict , runtime ); 375 if( ! runtime.is() ) 376 { 377 throw RuntimeException( 378 OUString( RTL_CONSTASCII_USTRINGPARAM("pyuno runtime is not initialized, " 379 "(the pyuno.bootstrap needs to be called before using any uno classes)")), 380 Reference< XInterface > () ); 381 } 382 impl = reinterpret_cast< RuntimeImpl * > (runtime.get()); 383 Py_XINCREF( runtime.get() ); 384 } 385 386 Runtime::Runtime( const Runtime & r ) 387 { 388 impl = r.impl; 389 Py_XINCREF( reinterpret_cast< PyObject * >(impl) ); 390 } 391 392 Runtime::~Runtime() 393 { 394 Py_XDECREF( reinterpret_cast< PyObject * >(impl) ); 395 } 396 397 Runtime & Runtime::operator = ( const Runtime & r ) 398 { 399 PyRef temp( reinterpret_cast< PyObject * >(r.impl) ); 400 Py_XINCREF( temp.get() ); 401 Py_XDECREF( reinterpret_cast< PyObject * >(impl) ); 402 impl = r.impl; 403 return *this; 404 } 405 406 PyRef Runtime::any2PyObject (const Any &a ) const 407 throw ( com::sun::star::script::CannotConvertException, 408 com::sun::star::lang::IllegalArgumentException, 409 RuntimeException) 410 { 411 if( ! impl->cargo->valid ) 412 { 413 throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM( 414 "pyuno runtime must be initialized before calling any2PyObject" )), 415 Reference< XInterface > () ); 416 } 417 418 switch (a.getValueTypeClass ()) 419 { 420 case typelib_TypeClass_VOID: 421 { 422 Py_INCREF (Py_None); 423 return PyRef(Py_None); 424 } 425 case typelib_TypeClass_CHAR: 426 { 427 sal_Unicode c = *(sal_Unicode*)a.getValue(); 428 return PyRef( PyUNO_char_new( c , *this ), SAL_NO_ACQUIRE ); 429 } 430 case typelib_TypeClass_BOOLEAN: 431 { 432 sal_Bool b = sal_Bool(); 433 if ((a >>= b) && b) 434 return Py_True; 435 else 436 return Py_False; 437 } 438 case typelib_TypeClass_BYTE: 439 case typelib_TypeClass_SHORT: 440 case typelib_TypeClass_UNSIGNED_SHORT: 441 case typelib_TypeClass_LONG: 442 { 443 sal_Int32 l = 0; 444 a >>= l; 445 return PyRef( PyInt_FromLong (l), SAL_NO_ACQUIRE ); 446 } 447 case typelib_TypeClass_UNSIGNED_LONG: 448 { 449 sal_uInt32 l = 0; 450 a >>= l; 451 return PyRef( PyLong_FromUnsignedLong (l), SAL_NO_ACQUIRE ); 452 } 453 case typelib_TypeClass_HYPER: 454 { 455 sal_Int64 l = 0; 456 a >>= l; 457 return PyRef( PyLong_FromLongLong (l), SAL_NO_ACQUIRE); 458 } 459 case typelib_TypeClass_UNSIGNED_HYPER: 460 { 461 sal_uInt64 l = 0; 462 a >>= l; 463 return PyRef( PyLong_FromUnsignedLongLong (l), SAL_NO_ACQUIRE); 464 } 465 case typelib_TypeClass_FLOAT: 466 { 467 float f = 0.0; 468 a >>= f; 469 return PyRef(PyFloat_FromDouble (f), SAL_NO_ACQUIRE); 470 } 471 case typelib_TypeClass_DOUBLE: 472 { 473 double d = 0.0; 474 a >>= d; 475 return PyRef( PyFloat_FromDouble (d), SAL_NO_ACQUIRE); 476 } 477 case typelib_TypeClass_STRING: 478 { 479 OUString tmp_ostr; 480 a >>= tmp_ostr; 481 return ustring2PyUnicode( tmp_ostr ); 482 } 483 case typelib_TypeClass_TYPE: 484 { 485 Type t; 486 a >>= t; 487 OString o = OUStringToOString( t.getTypeName(), RTL_TEXTENCODING_ASCII_US ); 488 return PyRef( 489 PyUNO_Type_new ( 490 o.getStr(), (com::sun::star::uno::TypeClass)t.getTypeClass(), *this), 491 SAL_NO_ACQUIRE); 492 } 493 case typelib_TypeClass_ANY: 494 { 495 //I don't think this can happen. 496 Py_INCREF (Py_None); 497 return Py_None; 498 } 499 case typelib_TypeClass_ENUM: 500 { 501 sal_Int32 l = *(sal_Int32 *) a.getValue(); 502 TypeDescription desc( a.getValueType() ); 503 if( desc.is() ) 504 { 505 desc.makeComplete(); 506 typelib_EnumTypeDescription *pEnumDesc = 507 (typelib_EnumTypeDescription *) desc.get(); 508 for( int i = 0 ; i < pEnumDesc->nEnumValues ; i ++ ) 509 { 510 if( pEnumDesc->pEnumValues[i] == l ) 511 { 512 OString v = OUStringToOString( pEnumDesc->ppEnumNames[i], RTL_TEXTENCODING_ASCII_US); 513 OString e = OUStringToOString( pEnumDesc->aBase.pTypeName, RTL_TEXTENCODING_ASCII_US); 514 return PyRef( PyUNO_Enum_new(e.getStr(),v.getStr(), *this ), SAL_NO_ACQUIRE ); 515 } 516 } 517 } 518 OUStringBuffer buf; 519 buf.appendAscii( "Any carries enum " ); 520 buf.append( a.getValueType().getTypeName()); 521 buf.appendAscii( " with invalid value " ).append( l ); 522 throw RuntimeException( buf.makeStringAndClear() , Reference< XInterface > () ); 523 } 524 case typelib_TypeClass_EXCEPTION: 525 case typelib_TypeClass_STRUCT: 526 { 527 PyRef excClass = getClass( a.getValueType().getTypeName(), *this ); 528 PyRef value = PyRef( PyUNO_new_UNCHECKED (a, getImpl()->cargo->xInvocation), SAL_NO_ACQUIRE); 529 PyRef argsTuple( PyTuple_New( 1 ) , SAL_NO_ACQUIRE ); 530 PyTuple_SetItem( argsTuple.get() , 0 , value.getAcquired() ); 531 PyRef ret( PyObject_CallObject( excClass.get() , argsTuple.get() ), SAL_NO_ACQUIRE ); 532 if( ! ret.is() ) 533 { 534 OUStringBuffer buf; 535 buf.appendAscii( "Couldn't instantiate python representation of structered UNO type " ); 536 buf.append( a.getValueType().getTypeName() ); 537 throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface > () ); 538 } 539 540 if( com::sun::star::uno::TypeClass_EXCEPTION == a.getValueTypeClass() ) 541 { 542 // add the message in a standard python way ! 543 PyRef args( PyTuple_New( 1 ), SAL_NO_ACQUIRE ); 544 545 // assuming that the Message is always the first member, wuuuu 546 void *pData = (void*)a.getValue(); 547 OUString message = *(OUString * )pData; 548 PyRef pymsg = ustring2PyString( message ); 549 PyTuple_SetItem( args.get(), 0 , pymsg.getAcquired() ); 550 // the exception base functions want to have an "args" tuple, 551 // which contains the message 552 PyObject_SetAttrString( ret.get(), const_cast< char * >("args"), args.get() ); 553 } 554 return ret; 555 } 556 case typelib_TypeClass_SEQUENCE: 557 { 558 Sequence<Any> s; 559 560 Sequence< sal_Int8 > byteSequence; 561 if( a >>= byteSequence ) 562 { 563 // byte sequence is treated in a special way because of peformance reasons 564 // @since 0.9.2 565 return PyRef( PyUNO_ByteSequence_new( byteSequence, *this ), SAL_NO_ACQUIRE ); 566 } 567 else 568 { 569 Reference< XTypeConverter > tc = getImpl()->cargo->xTypeConverter; 570 Reference< XSingleServiceFactory > ssf = getImpl()->cargo->xInvocation; 571 tc->convertTo (a, ::getCppuType (&s)) >>= s; 572 PyRef tuple( PyTuple_New (s.getLength()), SAL_NO_ACQUIRE); 573 int i=0; 574 OUString errMsg; 575 try 576 { 577 for ( i = 0; i < s.getLength (); i++) 578 { 579 PyRef element; 580 element = any2PyObject (tc->convertTo (s[i], s[i].getValueType() )); 581 OSL_ASSERT( element.is() ); 582 PyTuple_SetItem( tuple.get(), i, element.getAcquired() ); 583 } 584 } 585 catch( com::sun::star::uno::Exception & ) 586 { 587 for( ; i < s.getLength() ; i ++ ) 588 { 589 Py_INCREF( Py_None ); 590 PyTuple_SetItem( tuple.get(), i, Py_None ); 591 } 592 throw; 593 } 594 return tuple; 595 } 596 } 597 case typelib_TypeClass_INTERFACE: 598 { 599 Reference< XUnoTunnel > tunnel; 600 a >>= tunnel; 601 if( tunnel.is() ) 602 { 603 sal_Int64 that = tunnel->getSomething( ::pyuno::Adapter::getUnoTunnelImplementationId() ); 604 if( that ) 605 return ((Adapter*)sal::static_int_cast< sal_IntPtr >(that))->getWrappedObject(); 606 } 607 //This is just like the struct case: 608 return PyRef( PyUNO_new (a, getImpl()->cargo->xInvocation), SAL_NO_ACQUIRE ); 609 } 610 default: 611 { 612 OUStringBuffer buf; 613 buf.appendAscii( "Unknonwn UNO type class " ); 614 buf.append( (sal_Int32 ) a.getValueTypeClass() ); 615 throw RuntimeException(buf.makeStringAndClear( ), Reference< XInterface > () ); 616 } 617 } 618 //We shouldn't be here... 619 Py_INCREF( Py_None ); 620 return Py_None; 621 } 622 623 static Sequence< Type > invokeGetTypes( const Runtime & r , PyObject * o ) 624 { 625 Sequence< Type > ret; 626 627 PyRef method( PyObject_GetAttrString( o , const_cast< char * >("getTypes") ), SAL_NO_ACQUIRE ); 628 raiseInvocationTargetExceptionWhenNeeded( r ); 629 if( method.is() && PyCallable_Check( method.get() ) ) 630 { 631 PyRef types( PyObject_CallObject( method.get(), 0 ) , SAL_NO_ACQUIRE ); 632 raiseInvocationTargetExceptionWhenNeeded( r ); 633 if( types.is() && PyTuple_Check( types.get() ) ) 634 { 635 int size = PyTuple_Size( types.get() ); 636 637 // add the XUnoTunnel interface for uno object identity concept (hack) 638 ret.realloc( size + 1 ); 639 for( int i = 0 ; i < size ; i ++ ) 640 { 641 Any a = r.pyObject2Any(PyTuple_GetItem(types.get(),i)); 642 a >>= ret[i]; 643 } 644 ret[size] = getCppuType( (Reference< com::sun::star::lang::XUnoTunnel> *) 0 ); 645 } 646 } 647 return ret; 648 } 649 650 Any Runtime::pyObject2Any ( const PyRef & source, enum ConversionMode mode ) const 651 throw ( com::sun::star::uno::RuntimeException ) 652 { 653 if( ! impl->cargo->valid ) 654 { 655 throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM( 656 "pyuno runtime must be initialized before calling any2PyObject" )), 657 Reference< XInterface > () ); 658 } 659 660 Any a; 661 PyObject *o = source.get(); 662 if( Py_None == o ) 663 { 664 665 } 666 else if (PyInt_Check (o)) 667 { 668 if( o == Py_True ) 669 { 670 sal_Bool b = sal_True; 671 a = Any( &b, getBooleanCppuType() ); 672 } 673 else if ( o == Py_False ) 674 { 675 sal_Bool b = sal_False; 676 a = Any( &b, getBooleanCppuType() ); 677 } 678 else 679 { 680 sal_Int32 l = (sal_Int32) PyInt_AsLong( o ); 681 if( l < 128 && l >= -128 ) 682 { 683 sal_Int8 b = (sal_Int8 ) l; 684 a <<= b; 685 } 686 else if( l <= 0x7fff && l >= -0x8000 ) 687 { 688 sal_Int16 s = (sal_Int16) l; 689 a <<= s; 690 } 691 else 692 { 693 a <<= l; 694 } 695 } 696 } 697 else if (PyLong_Check (o)) 698 { 699 sal_Int64 l = (sal_Int64)PyLong_AsLong (o); 700 if( l < 128 && l >= -128 ) 701 { 702 sal_Int8 b = (sal_Int8 ) l; 703 a <<= b; 704 } 705 else if( l <= 0x7fff && l >= -0x8000 ) 706 { 707 sal_Int16 s = (sal_Int16) l; 708 a <<= s; 709 } 710 else if( l <= SAL_CONST_INT64(0x7fffffff) && 711 l >= -SAL_CONST_INT64(0x80000000) ) 712 { 713 sal_Int32 l32 = (sal_Int32) l; 714 a <<= l32; 715 } 716 else 717 { 718 a <<= l; 719 } 720 } 721 else if (PyFloat_Check (o)) 722 { 723 double d = PyFloat_AsDouble (o); 724 a <<= d; 725 } 726 else if (PyString_Check (o)) 727 a <<= pyString2ustring(o); 728 else if( PyUnicode_Check( o ) ) 729 a <<= pyString2ustring(o); 730 else if (PyTuple_Check (o)) 731 { 732 Sequence<Any> s (PyTuple_Size (o)); 733 for (int i = 0; i < PyTuple_Size (o); i++) 734 { 735 s[i] = pyObject2Any (PyTuple_GetItem (o, i), mode ); 736 } 737 a <<= s; 738 } 739 else 740 { 741 Runtime runtime; 742 // should be removed, in case ByteSequence gets derived from String 743 if( PyObject_IsInstance( o, getByteSequenceClass( runtime ).get() ) ) 744 { 745 PyRef str(PyObject_GetAttrString( o , const_cast< char * >("value") ),SAL_NO_ACQUIRE); 746 Sequence< sal_Int8 > seq; 747 if( PyString_Check( str.get() ) ) 748 { 749 seq = Sequence<sal_Int8 > ( 750 (sal_Int8*) PyString_AsString(str.get()), PyString_Size(str.get())); 751 } 752 a <<= seq; 753 } 754 else 755 if( PyObject_IsInstance( o, getTypeClass( runtime ).get() ) ) 756 { 757 Type t = PyType2Type( o ); 758 a <<= t; 759 } 760 else if( PyObject_IsInstance( o, getEnumClass( runtime ).get() ) ) 761 { 762 a = PyEnum2Enum( o ); 763 } 764 else if( isInstanceOfStructOrException( o ) ) 765 { 766 PyRef struc(PyObject_GetAttrString( o , const_cast< char * >("value") ),SAL_NO_ACQUIRE); 767 PyUNO * obj = (PyUNO*)struc.get(); 768 Reference< XMaterialHolder > holder( obj->members->xInvocation, UNO_QUERY ); 769 if( holder.is( ) ) 770 a = holder->getMaterial(); 771 else 772 { 773 throw RuntimeException( 774 USTR_ASCII( "struct or exception wrapper does not support XMaterialHolder" ), 775 Reference< XInterface > () ); 776 } 777 } 778 else if( PyObject_IsInstance( o, getPyUnoClass( runtime ).get() ) ) 779 { 780 PyUNO* o_pi; 781 o_pi = (PyUNO*) o; 782 if (o_pi->members->wrappedObject.getValueTypeClass () == 783 com::sun::star::uno::TypeClass_STRUCT || 784 o_pi->members->wrappedObject.getValueTypeClass () == 785 com::sun::star::uno::TypeClass_EXCEPTION) 786 { 787 Reference<XMaterialHolder> my_mh (o_pi->members->xInvocation, UNO_QUERY); 788 789 if (!my_mh.is ()) 790 { 791 throw RuntimeException( 792 USTR_ASCII( "struct wrapper does not support XMaterialHolder" ), 793 Reference< XInterface > () ); 794 } 795 else 796 a = my_mh->getMaterial (); 797 } 798 else 799 { 800 a = o_pi->members->wrappedObject; 801 } 802 } 803 else if( PyObject_IsInstance( o, getCharClass( runtime ).get() ) ) 804 { 805 sal_Unicode c = PyChar2Unicode( o ); 806 a.setValue( &c, getCharCppuType( )); 807 } 808 else if( PyObject_IsInstance( o, getAnyClass( runtime ).get() ) ) 809 { 810 if( ACCEPT_UNO_ANY == mode ) 811 { 812 a = pyObject2Any( PyRef( PyObject_GetAttrString( o , const_cast< char * >("value") ), SAL_NO_ACQUIRE) ); 813 Type t; 814 pyObject2Any( PyRef( PyObject_GetAttrString( o, const_cast< char * >("type") ), SAL_NO_ACQUIRE ) ) >>= t; 815 816 try 817 { 818 a = getImpl()->cargo->xTypeConverter->convertTo( a, t ); 819 } 820 catch( com::sun::star::uno::Exception & e ) 821 { 822 throw RuntimeException( e.Message, e.Context ); 823 } 824 } 825 else 826 { 827 throw RuntimeException( 828 OUString( RTL_CONSTASCII_USTRINGPARAM( 829 "uno.Any instance not accepted during method call, " 830 "use uno.invoke instead" ) ), 831 Reference< XInterface > () ); 832 } 833 } 834 else 835 { 836 Reference< XInterface > mappedObject; 837 Reference< XInvocation > adapterObject; 838 839 // instance already mapped out to the world ? 840 PyRef2Adapter::iterator ii = impl->cargo->mappedObjects.find( PyRef( o ) ); 841 if( ii != impl->cargo->mappedObjects.end() ) 842 { 843 adapterObject = ii->second; 844 } 845 846 if( adapterObject.is() ) 847 { 848 // object got already bridged ! 849 Reference< com::sun::star::lang::XUnoTunnel > tunnel( adapterObject, UNO_QUERY ); 850 851 Adapter *pAdapter = ( Adapter * ) 852 sal::static_int_cast< sal_IntPtr >( 853 tunnel->getSomething( 854 ::pyuno::Adapter::getUnoTunnelImplementationId() ) ); 855 856 mappedObject = impl->cargo->xAdapterFactory->createAdapter( 857 adapterObject, pAdapter->getWrappedTypes() ); 858 } 859 else 860 { 861 Sequence< Type > interfaces = invokeGetTypes( *this, o ); 862 if( interfaces.getLength() ) 863 { 864 Adapter *pAdapter = new Adapter( o, interfaces ); 865 mappedObject = 866 getImpl()->cargo->xAdapterFactory->createAdapter( 867 pAdapter, interfaces ); 868 869 // keep a list of exported objects to ensure object identity ! 870 impl->cargo->mappedObjects[ PyRef(o) ] = 871 com::sun::star::uno::WeakReference< XInvocation > ( pAdapter ); 872 } 873 } 874 if( mappedObject.is() ) 875 { 876 a = com::sun::star::uno::makeAny( mappedObject ); 877 } 878 else 879 { 880 OUStringBuffer buf; 881 buf.appendAscii( "Couldn't convert " ); 882 PyRef reprString( PyObject_Str( o ) , SAL_NO_ACQUIRE ); 883 buf.appendAscii( PyString_AsString( reprString.get() ) ); 884 buf.appendAscii( " to a UNO type" ); 885 throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface > () ); 886 } 887 } 888 } 889 return a; 890 } 891 892 Any Runtime::extractUnoException( const PyRef & excType, const PyRef &excValue, const PyRef &excTraceback) const 893 { 894 PyRef str; 895 Any ret; 896 if( excTraceback.is() ) 897 { 898 PyRef unoModule( impl ? impl->cargo->getUnoModule() : 0 ); 899 if( unoModule.is() ) 900 { 901 PyRef extractTraceback( 902 PyDict_GetItemString(unoModule.get(),"_uno_extract_printable_stacktrace" ) ); 903 904 if( extractTraceback.is() ) 905 { 906 PyRef args( PyTuple_New( 1), SAL_NO_ACQUIRE ); 907 PyTuple_SetItem( args.get(), 0, excTraceback.getAcquired() ); 908 str = PyRef( PyObject_CallObject( extractTraceback.get(),args.get() ), SAL_NO_ACQUIRE); 909 } 910 else 911 { 912 str = PyRef( 913 PyString_FromString( "Couldn't find uno._uno_extract_printable_stacktrace" ), 914 SAL_NO_ACQUIRE ); 915 } 916 } 917 else 918 { 919 str = PyRef( 920 PyString_FromString( "Couldn't find uno.py, no stacktrace available" ), 921 SAL_NO_ACQUIRE ); 922 } 923 924 } 925 else 926 { 927 // it may occur, that no traceback is given (e.g. only native code below) 928 str = PyRef( PyString_FromString( "no traceback available" ), SAL_NO_ACQUIRE); 929 } 930 931 if( isInstanceOfStructOrException( excValue.get() ) ) 932 { 933 ret = pyObject2Any( excValue ); 934 } 935 else 936 { 937 OUStringBuffer buf; 938 PyRef typeName( PyObject_Str( excType.get() ), SAL_NO_ACQUIRE ); 939 if( typeName.is() ) 940 { 941 buf.appendAscii( PyString_AsString( typeName.get() ) ); 942 } 943 else 944 { 945 buf.appendAscii( "no typename available" ); 946 } 947 buf.appendAscii( ": " ); 948 PyRef valueRep( PyObject_Str( excValue.get() ), SAL_NO_ACQUIRE ); 949 if( valueRep.is() ) 950 { 951 buf.appendAscii( PyString_AsString( valueRep.get())); 952 } 953 else 954 { 955 buf.appendAscii( "Couldn't convert exception value to a string" ); 956 } 957 buf.appendAscii( ", traceback follows\n" ); 958 if( str.is() ) 959 { 960 buf.appendAscii( PyString_AsString( str.get() ) ); 961 } 962 else 963 { 964 buf.appendAscii( ", no traceback available\n" ); 965 } 966 RuntimeException e; 967 e.Message = buf.makeStringAndClear(); 968 ret = com::sun::star::uno::makeAny( e ); 969 } 970 return ret; 971 } 972 973 974 static const char * g_NUMERICID = "pyuno.lcNumeric"; 975 static ::std::vector< rtl::OString > g_localeList; 976 977 static const char *ensureUnlimitedLifetime( const char *str ) 978 { 979 int size = g_localeList.size(); 980 int i; 981 for( i = 0 ; i < size ; i ++ ) 982 { 983 if( 0 == strcmp( g_localeList[i].getStr(), str ) ) 984 break; 985 } 986 if( i == size ) 987 { 988 g_localeList.push_back( str ); 989 } 990 return g_localeList[i].getStr(); 991 } 992 993 994 PyThreadAttach::PyThreadAttach( PyInterpreterState *interp) 995 throw ( com::sun::star::uno::RuntimeException ) 996 { 997 tstate = PyThreadState_New( interp ); 998 if( !tstate ) 999 throw RuntimeException( 1000 OUString(RTL_CONSTASCII_USTRINGPARAM( "Couldn't create a pythreadstate" ) ), 1001 Reference< XInterface > () ); 1002 PyEval_AcquireThread( tstate); 1003 // set LC_NUMERIC to "C" 1004 const char * oldLocale = 1005 ensureUnlimitedLifetime( setlocale( LC_NUMERIC, 0 ) ); 1006 setlocale( LC_NUMERIC, "C" ); 1007 PyRef locale( // python requires C locale 1008 PyLong_FromVoidPtr( (void*)oldLocale ), SAL_NO_ACQUIRE); 1009 PyDict_SetItemString( 1010 PyThreadState_GetDict(), g_NUMERICID, locale.get() ); 1011 } 1012 1013 PyThreadAttach::~PyThreadAttach() 1014 { 1015 PyObject *value = 1016 PyDict_GetItemString( PyThreadState_GetDict( ), g_NUMERICID ); 1017 if( value ) 1018 setlocale( LC_NUMERIC, (const char * ) PyLong_AsVoidPtr( value ) ); 1019 PyThreadState_Clear( tstate ); 1020 PyEval_ReleaseThread( tstate ); 1021 PyThreadState_Delete( tstate ); 1022 1023 } 1024 1025 PyThreadDetach::PyThreadDetach() throw ( com::sun::star::uno::RuntimeException ) 1026 { 1027 tstate = PyThreadState_Get(); 1028 PyObject *value = 1029 PyDict_GetItemString( PyThreadState_GetDict( ), g_NUMERICID ); 1030 if( value ) 1031 setlocale( LC_NUMERIC, (const char * ) PyLong_AsVoidPtr( value ) ); 1032 PyEval_ReleaseThread( tstate ); 1033 } 1034 1035 /** Acquires the global interpreter lock again 1036 1037 */ 1038 PyThreadDetach::~PyThreadDetach() 1039 { 1040 PyEval_AcquireThread( tstate ); 1041 // PyObject *value = 1042 // PyDict_GetItemString( PyThreadState_GetDict( ), g_NUMERICID ); 1043 1044 // python requires C LC_NUMERIC locale, 1045 // always set even when it is already "C" 1046 setlocale( LC_NUMERIC, "C" ); 1047 } 1048 1049 1050 PyRef RuntimeCargo::getUnoModule() 1051 { 1052 if( ! dictUnoModule.is() ) 1053 { 1054 dictUnoModule = importUnoModule(); 1055 } 1056 return dictUnoModule; 1057 } 1058 } 1059