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