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