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