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