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