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 #if PY_MAJOR_VERSION < 3 // Python 3 has no PyInt 666 else if (PyInt_Check (o)) 667 { 668 if( o == Py_True ) 669 { 670 sal_Bool b = sal_True; 671 a = Any( &b, getBooleanCppuType() ); 672 } 673 else if ( o == Py_False ) 674 { 675 sal_Bool b = sal_False; 676 a = Any( &b, getBooleanCppuType() ); 677 } 678 else 679 { 680 sal_Int32 l = (sal_Int32) PyInt_AsLong( o ); 681 if( l < 128 && l >= -128 ) 682 { 683 sal_Int8 b = (sal_Int8 ) l; 684 a <<= b; 685 } 686 else if( l <= 0x7fff && l >= -0x8000 ) 687 { 688 sal_Int16 s = (sal_Int16) l; 689 a <<= s; 690 } 691 else 692 { 693 a <<= l; 694 } 695 } 696 } 697 #endif // Python 3 has no PyInt 698 else if (PyLong_Check (o)) 699 { 700 sal_Int64 l = (sal_Int64)PyLong_AsLong (o); 701 if( l < 128 && l >= -128 ) 702 { 703 sal_Int8 b = (sal_Int8 ) l; 704 a <<= b; 705 } 706 else if( l <= 0x7fff && l >= -0x8000 ) 707 { 708 sal_Int16 s = (sal_Int16) l; 709 a <<= s; 710 } 711 else if( l <= SAL_CONST_INT64(0x7fffffff) && 712 l >= -SAL_CONST_INT64(0x80000000) ) 713 { 714 sal_Int32 l32 = (sal_Int32) l; 715 a <<= l32; 716 } 717 else 718 { 719 a <<= l; 720 } 721 } 722 else if (PyFloat_Check (o)) 723 { 724 double d = PyFloat_AsDouble (o); 725 a <<= d; 726 } 727 else if (PyBytes_Check (o)) 728 a <<= pyString2ustring(o); 729 else if( PyUnicode_Check( o ) ) 730 a <<= pyString2ustring(o); 731 else if (PyTuple_Check (o)) 732 { 733 Sequence<Any> s (PyTuple_Size (o)); 734 for (int i = 0; i < PyTuple_Size (o); i++) 735 { 736 s[i] = pyObject2Any (PyTuple_GetItem (o, i), mode ); 737 } 738 a <<= s; 739 } 740 else 741 { 742 Runtime runtime; 743 // should be removed, in case ByteSequence gets derived from String 744 if( PyObject_IsInstance( o, getByteSequenceClass( runtime ).get() ) ) 745 { 746 PyRef str(PyObject_GetAttrString( o , const_cast< char * >("value") ),SAL_NO_ACQUIRE); 747 Sequence< sal_Int8 > seq; 748 if( PyBytes_Check( str.get() ) ) 749 { 750 seq = Sequence<sal_Int8 > ( 751 (sal_Int8*) PyBytes_AsString(str.get()), PyBytes_Size(str.get())); 752 } 753 a <<= seq; 754 } 755 else 756 if( PyObject_IsInstance( o, getTypeClass( runtime ).get() ) ) 757 { 758 Type t = PyType2Type( o ); 759 a <<= t; 760 } 761 else if( PyObject_IsInstance( o, getEnumClass( runtime ).get() ) ) 762 { 763 a = PyEnum2Enum( o ); 764 } 765 else if( isInstanceOfStructOrException( o ) ) 766 { 767 PyRef struc(PyObject_GetAttrString( o , const_cast< char * >("value") ),SAL_NO_ACQUIRE); 768 PyUNO * obj = (PyUNO*)struc.get(); 769 Reference< XMaterialHolder > holder( obj->members->xInvocation, UNO_QUERY ); 770 if( holder.is( ) ) 771 a = holder->getMaterial(); 772 else 773 { 774 throw RuntimeException( 775 USTR_ASCII( "struct or exception wrapper does not support XMaterialHolder" ), 776 Reference< XInterface > () ); 777 } 778 } 779 else if( PyObject_IsInstance( o, getPyUnoClass( runtime ).get() ) ) 780 { 781 PyUNO* o_pi; 782 o_pi = (PyUNO*) o; 783 if (o_pi->members->wrappedObject.getValueTypeClass () == 784 com::sun::star::uno::TypeClass_STRUCT || 785 o_pi->members->wrappedObject.getValueTypeClass () == 786 com::sun::star::uno::TypeClass_EXCEPTION) 787 { 788 Reference<XMaterialHolder> my_mh (o_pi->members->xInvocation, UNO_QUERY); 789 790 if (!my_mh.is ()) 791 { 792 throw RuntimeException( 793 USTR_ASCII( "struct wrapper does not support XMaterialHolder" ), 794 Reference< XInterface > () ); 795 } 796 else 797 a = my_mh->getMaterial (); 798 } 799 else 800 { 801 a = o_pi->members->wrappedObject; 802 } 803 } 804 else if( PyObject_IsInstance( o, getCharClass( runtime ).get() ) ) 805 { 806 sal_Unicode c = PyChar2Unicode( o ); 807 a.setValue( &c, getCharCppuType( )); 808 } 809 else if( PyObject_IsInstance( o, getAnyClass( runtime ).get() ) ) 810 { 811 if( ACCEPT_UNO_ANY == mode ) 812 { 813 a = pyObject2Any( PyRef( PyObject_GetAttrString( o , const_cast< char * >("value") ), SAL_NO_ACQUIRE) ); 814 Type t; 815 pyObject2Any( PyRef( PyObject_GetAttrString( o, const_cast< char * >("type") ), SAL_NO_ACQUIRE ) ) >>= t; 816 817 try 818 { 819 a = getImpl()->cargo->xTypeConverter->convertTo( a, t ); 820 } 821 catch( com::sun::star::uno::Exception & e ) 822 { 823 throw RuntimeException( e.Message, e.Context ); 824 } 825 } 826 else 827 { 828 throw RuntimeException( 829 OUString( RTL_CONSTASCII_USTRINGPARAM( 830 "uno.Any instance not accepted during method call, " 831 "use uno.invoke instead" ) ), 832 Reference< XInterface > () ); 833 } 834 } 835 else 836 { 837 Reference< XInterface > mappedObject; 838 Reference< XInvocation > adapterObject; 839 840 // instance already mapped out to the world ? 841 PyRef2Adapter::iterator ii = impl->cargo->mappedObjects.find( PyRef( o ) ); 842 if( ii != impl->cargo->mappedObjects.end() ) 843 { 844 adapterObject = ii->second; 845 } 846 847 if( adapterObject.is() ) 848 { 849 // object got already bridged ! 850 Reference< com::sun::star::lang::XUnoTunnel > tunnel( adapterObject, UNO_QUERY ); 851 852 Adapter *pAdapter = ( Adapter * ) 853 sal::static_int_cast< sal_IntPtr >( 854 tunnel->getSomething( 855 ::pyuno::Adapter::getUnoTunnelImplementationId() ) ); 856 857 mappedObject = impl->cargo->xAdapterFactory->createAdapter( 858 adapterObject, pAdapter->getWrappedTypes() ); 859 } 860 else 861 { 862 Sequence< Type > interfaces = invokeGetTypes( *this, o ); 863 if( interfaces.getLength() ) 864 { 865 Adapter *pAdapter = new Adapter( o, interfaces ); 866 mappedObject = 867 getImpl()->cargo->xAdapterFactory->createAdapter( 868 pAdapter, interfaces ); 869 870 // keep a list of exported objects to ensure object identity ! 871 impl->cargo->mappedObjects[ PyRef(o) ] = 872 com::sun::star::uno::WeakReference< XInvocation > ( pAdapter ); 873 } 874 } 875 if( mappedObject.is() ) 876 { 877 a = com::sun::star::uno::makeAny( mappedObject ); 878 } 879 else 880 { 881 OUStringBuffer buf; 882 buf.appendAscii( "Couldn't convert " ); 883 PyRef reprString( PyObject_Str( o ) , SAL_NO_ACQUIRE ); 884 buf.appendAscii( PyBytes_AsString( reprString.get() ) ); 885 buf.appendAscii( " to a UNO type" ); 886 throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface > () ); 887 } 888 } 889 } 890 return a; 891 } 892 893 Any Runtime::extractUnoException( const PyRef & excType, const PyRef &excValue, const PyRef &excTraceback) const 894 { 895 PyRef str; 896 Any ret; 897 if( excTraceback.is() ) 898 { 899 PyRef unoModule( impl ? impl->cargo->getUnoModule() : 0 ); 900 if( unoModule.is() ) 901 { 902 PyRef extractTraceback( 903 PyDict_GetItemString(unoModule.get(),"_uno_extract_printable_stacktrace" ) ); 904 905 if( extractTraceback.is() ) 906 { 907 PyRef args( PyTuple_New( 1), SAL_NO_ACQUIRE ); 908 PyTuple_SetItem( args.get(), 0, excTraceback.getAcquired() ); 909 str = PyRef( PyObject_CallObject( extractTraceback.get(),args.get() ), SAL_NO_ACQUIRE); 910 } 911 else 912 { 913 str = PyRef( 914 PyBytes_FromString( "Couldn't find uno._uno_extract_printable_stacktrace" ), 915 SAL_NO_ACQUIRE ); 916 } 917 } 918 else 919 { 920 str = PyRef( 921 PyBytes_FromString( "Couldn't find uno.py, no stacktrace available" ), 922 SAL_NO_ACQUIRE ); 923 } 924 925 } 926 else 927 { 928 // it may occur, that no traceback is given (e.g. only native code below) 929 str = PyRef( PyBytes_FromString( "no traceback available" ), SAL_NO_ACQUIRE); 930 } 931 932 if( isInstanceOfStructOrException( excValue.get() ) ) 933 { 934 ret = pyObject2Any( excValue ); 935 } 936 else 937 { 938 OUStringBuffer buf; 939 PyRef typeName( PyObject_Str( excType.get() ), SAL_NO_ACQUIRE ); 940 if( typeName.is() ) 941 { 942 buf.appendAscii( PyBytes_AsString( typeName.get() ) ); 943 } 944 else 945 { 946 buf.appendAscii( "no typename available" ); 947 } 948 buf.appendAscii( ": " ); 949 PyRef valueRep( PyObject_Str( excValue.get() ), SAL_NO_ACQUIRE ); 950 if( valueRep.is() ) 951 { 952 buf.appendAscii( PyBytes_AsString( valueRep.get())); 953 } 954 else 955 { 956 buf.appendAscii( "Couldn't convert exception value to a string" ); 957 } 958 buf.appendAscii( ", traceback follows\n" ); 959 if( str.is() ) 960 { 961 buf.appendAscii( PyBytes_AsString( str.get() ) ); 962 } 963 else 964 { 965 buf.appendAscii( ", no traceback available\n" ); 966 } 967 RuntimeException e; 968 e.Message = buf.makeStringAndClear(); 969 ret = com::sun::star::uno::makeAny( e ); 970 } 971 return ret; 972 } 973 974 975 static const char * g_NUMERICID = "pyuno.lcNumeric"; 976 static ::std::vector< rtl::OString > g_localeList; 977 978 static const char *ensureUnlimitedLifetime( const char *str ) 979 { 980 int size = g_localeList.size(); 981 int i; 982 for( i = 0 ; i < size ; i ++ ) 983 { 984 if( 0 == strcmp( g_localeList[i].getStr(), str ) ) 985 break; 986 } 987 if( i == size ) 988 { 989 g_localeList.push_back( str ); 990 } 991 return g_localeList[i].getStr(); 992 } 993 994 995 PyThreadAttach::PyThreadAttach( PyInterpreterState *interp) 996 throw ( com::sun::star::uno::RuntimeException ) 997 { 998 tstate = PyThreadState_New( interp ); 999 if( !tstate ) 1000 throw RuntimeException( 1001 OUString(RTL_CONSTASCII_USTRINGPARAM( "Couldn't create a pythreadstate" ) ), 1002 Reference< XInterface > () ); 1003 PyEval_AcquireThread( tstate); 1004 // set LC_NUMERIC to "C" 1005 const char * oldLocale = 1006 ensureUnlimitedLifetime( setlocale( LC_NUMERIC, 0 ) ); 1007 setlocale( LC_NUMERIC, "C" ); 1008 PyRef locale( // python requires C locale 1009 PyLong_FromVoidPtr( (void*)oldLocale ), SAL_NO_ACQUIRE); 1010 PyDict_SetItemString( 1011 PyThreadState_GetDict(), g_NUMERICID, locale.get() ); 1012 } 1013 1014 PyThreadAttach::~PyThreadAttach() 1015 { 1016 PyObject *value = 1017 PyDict_GetItemString( PyThreadState_GetDict( ), g_NUMERICID ); 1018 if( value ) 1019 setlocale( LC_NUMERIC, (const char * ) PyLong_AsVoidPtr( value ) ); 1020 PyThreadState_Clear( tstate ); 1021 PyEval_ReleaseThread( tstate ); 1022 PyThreadState_Delete( tstate ); 1023 1024 } 1025 1026 PyThreadDetach::PyThreadDetach() throw ( com::sun::star::uno::RuntimeException ) 1027 { 1028 tstate = PyThreadState_Get(); 1029 PyObject *value = 1030 PyDict_GetItemString( PyThreadState_GetDict( ), g_NUMERICID ); 1031 if( value ) 1032 setlocale( LC_NUMERIC, (const char * ) PyLong_AsVoidPtr( value ) ); 1033 PyEval_ReleaseThread( tstate ); 1034 } 1035 1036 /** Acquires the global interpreter lock again 1037 1038 */ 1039 PyThreadDetach::~PyThreadDetach() 1040 { 1041 PyEval_AcquireThread( tstate ); 1042 // PyObject *value = 1043 // PyDict_GetItemString( PyThreadState_GetDict( ), g_NUMERICID ); 1044 1045 // python requires C LC_NUMERIC locale, 1046 // always set even when it is already "C" 1047 setlocale( LC_NUMERIC, "C" ); 1048 } 1049 1050 1051 PyRef RuntimeCargo::getUnoModule() 1052 { 1053 if( ! dictUnoModule.is() ) 1054 { 1055 dictUnoModule = importUnoModule(); 1056 } 1057 return dictUnoModule; 1058 } 1059 } 1060