Version 5.2.6.1, tag libreoffice-5.2.6.1
[LibreOffice.git] / pyuno / source / module / pyuno_runtime.cxx
blob468d21f5b57d6c3e8858fa67ebe4ab5f6c5c3f41
1 /* -*- Mode: C++; eval:(c-set-style "bsd"); tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_features.h>
21 #include <config_folders.h>
23 #include "pyuno_impl.hxx"
25 #include <osl/diagnose.h>
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>
33 #include <list>
34 #include <typelib/typedescription.hxx>
36 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
37 #include <com/sun/star/beans/XMaterialHolder.hpp>
38 #include <com/sun/star/beans/theIntrospection.hpp>
39 #include <com/sun/star/script/Converter.hpp>
40 #include <com/sun/star/script/InvocationAdapterFactory.hpp>
41 #include <com/sun/star/reflection/theCoreReflection.hpp>
42 #include <comphelper/sequence.hxx>
45 using com::sun::star::uno::Reference;
46 using com::sun::star::uno::XInterface;
47 using com::sun::star::uno::Any;
48 using com::sun::star::uno::TypeDescription;
49 using com::sun::star::uno::Sequence;
50 using com::sun::star::uno::Type;
51 using com::sun::star::uno::UNO_QUERY;
52 using com::sun::star::uno::Exception;
53 using com::sun::star::uno::RuntimeException;
54 using com::sun::star::uno::XComponentContext;
55 using com::sun::star::lang::WrappedTargetRuntimeException;
56 using com::sun::star::lang::XSingleServiceFactory;
57 using com::sun::star::lang::XUnoTunnel;
58 using com::sun::star::reflection::theCoreReflection;
59 using com::sun::star::reflection::InvocationTargetException;
60 using com::sun::star::script::Converter;
61 using com::sun::star::script::XTypeConverter;
62 using com::sun::star::script::XInvocation;
63 using com::sun::star::beans::XMaterialHolder;
64 using com::sun::star::beans::theIntrospection;
66 #include <vector>
68 namespace pyuno
71 static PyTypeObject RuntimeImpl_Type =
73 PyVarObject_HEAD_INIT (&PyType_Type, 0)
74 "pyuno_runtime",
75 sizeof (RuntimeImpl),
77 RuntimeImpl::del,
78 nullptr,
79 nullptr,
80 nullptr,
81 nullptr,
82 nullptr,
83 nullptr,
84 nullptr,
85 nullptr,
86 nullptr,
87 nullptr,
88 nullptr,
89 nullptr,
90 nullptr,
91 nullptr,
93 nullptr,
94 nullptr,
95 nullptr,
96 nullptr,
98 nullptr,
99 nullptr,
100 nullptr,
101 nullptr,
102 nullptr,
103 nullptr,
104 nullptr,
105 nullptr,
106 nullptr,
108 nullptr,
109 nullptr,
110 nullptr,
111 nullptr,
112 nullptr,
113 nullptr,
114 nullptr,
115 nullptr,
116 nullptr,
117 nullptr,
118 nullptr
119 #if PY_VERSION_HEX >= 0x02060000
121 #endif
122 #if PY_VERSION_HEX >= 0x03040000
123 , nullptr
124 #endif
127 /*----------------------------------------------------------------------
128 Runtime implementation
129 -----------------------------------------------------------------------*/
130 static void getRuntimeImpl( PyRef & globalDict, PyRef &runtimeImpl )
131 throw ( css::uno::RuntimeException )
133 PyThreadState * state = PyThreadState_Get();
134 if( ! state )
136 throw RuntimeException( "python global interpreter must be held (thread must be attached)" );
139 PyObject* pModule = PyImport_AddModule("__main__");
141 if (!pModule)
143 throw RuntimeException("can't import __main__ module");
146 globalDict = PyRef( PyModule_GetDict(pModule));
148 if( ! globalDict.is() ) // FATAL !
150 throw RuntimeException("can't find __main__ module");
152 runtimeImpl = PyDict_GetItemString( globalDict.get() , "pyuno_runtime" );
155 static PyRef importUnoModule( ) throw ( RuntimeException )
157 // import the uno module
158 PyRef module( PyImport_ImportModule( "uno" ), SAL_NO_ACQUIRE, NOT_NULL );
159 if( PyErr_Occurred() )
161 PyRef excType, excValue, excTraceback;
162 PyErr_Fetch( reinterpret_cast<PyObject **>(&excType), reinterpret_cast<PyObject**>(&excValue), reinterpret_cast<PyObject**>(&excTraceback));
163 // As of Python 2.7 this gives a rather non-useful "<traceback object at 0xADDRESS>",
164 // but it is the best we can do in the absence of uno._uno_extract_printable_stacktrace
165 // Who knows, a future Python might print something better.
166 PyRef str( PyObject_Str( excTraceback.get() ), SAL_NO_ACQUIRE );
168 OUStringBuffer buf;
169 buf.append( "python object raised an unknown exception (" );
170 PyRef valueRep( PyObject_Repr( excValue.get() ), SAL_NO_ACQUIRE );
171 buf.appendAscii( PyStr_AsString( valueRep.get())).append( ", traceback follows\n" );
172 buf.appendAscii( PyStr_AsString( str.get() ) );
173 buf.append( ")" );
174 throw RuntimeException( buf.makeStringAndClear() );
176 PyRef dict( PyModule_GetDict( module.get() ) );
177 return dict;
180 static void readLoggingConfig( sal_Int32 *pLevel, FILE **ppFile )
182 *pLevel = LogLevel::NONE;
183 *ppFile = nullptr;
184 OUString fileName;
185 osl_getModuleURLFromFunctionAddress(
186 reinterpret_cast< oslGenericFunction >(readLoggingConfig),
187 &fileName.pData );
188 fileName = fileName.copy( fileName.lastIndexOf( '/' )+1 );
189 #ifdef MACOSX
190 fileName += "../" LIBO_ETC_FOLDER "/";
191 #endif
192 fileName += SAL_CONFIGFILE("pyuno" );
193 rtl::Bootstrap bootstrapHandle( fileName );
195 OUString str;
196 if( bootstrapHandle.getFrom( "PYUNO_LOGLEVEL", str ) )
198 if ( str == "NONE" )
199 *pLevel = LogLevel::NONE;
200 else if ( str == "CALL" )
201 *pLevel = LogLevel::CALL;
202 else if ( str == "ARGS" )
203 *pLevel = LogLevel::ARGS;
204 else
206 fprintf( stderr, "unknown loglevel %s\n",
207 OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
210 if( *pLevel > LogLevel::NONE )
212 *ppFile = stdout;
213 if( bootstrapHandle.getFrom( "PYUNO_LOGTARGET", str ) )
215 if ( str == "stdout" )
216 *ppFile = stdout;
217 else if ( str == "stderr" )
218 *ppFile = stderr;
219 else
221 oslProcessInfo data;
222 data.Size = sizeof( data );
223 osl_getProcessInfo(
224 nullptr , osl_Process_IDENTIFIER , &data );
225 osl_getSystemPathFromFileURL( str.pData, &str.pData);
226 OString o = OUStringToOString( str, osl_getThreadTextEncoding() );
227 o += ".";
228 o += OString::number( data.Ident );
230 *ppFile = fopen( o.getStr() , "w" );
231 if ( *ppFile )
233 // do not buffer (useful if e.g. analyzing a crash)
234 setvbuf( *ppFile, nullptr, _IONBF, 0 );
236 else
238 fprintf( stderr, "couldn't create file %s\n",
239 OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
247 /*-------------------------------------------------------------------
248 RuntimeImpl implementations
249 *-------------------------------------------------------------------*/
250 PyRef stRuntimeImpl::create( const Reference< XComponentContext > &ctx )
251 throw( css::uno::RuntimeException, std::exception )
253 RuntimeImpl *me = PyObject_New (RuntimeImpl, &RuntimeImpl_Type);
254 if( ! me )
255 throw RuntimeException( "cannot instantiate pyuno::RuntimeImpl" );
256 me->cargo = nullptr;
257 // must use a different struct here, as the PyObject_New
258 // makes C++ unusable
259 RuntimeCargo *c = new RuntimeCargo();
260 readLoggingConfig( &(c->logLevel) , &(c->logFile) );
261 log( c, LogLevel::CALL, "Instantiating pyuno bridge" );
263 c->valid = true;
264 c->xContext = ctx;
265 c->xInvocation = Reference< XSingleServiceFactory > (
266 ctx->getServiceManager()->createInstanceWithContext(
267 "com.sun.star.script.Invocation",
268 ctx ),
269 UNO_QUERY );
270 if( ! c->xInvocation.is() )
271 throw RuntimeException( "pyuno: couldn't instantiate invocation service" );
273 c->xTypeConverter = Converter::create(ctx);
274 if( ! c->xTypeConverter.is() )
275 throw RuntimeException( "pyuno: couldn't instantiate typeconverter service" );
277 c->xCoreReflection = theCoreReflection::get(ctx);
279 c->xAdapterFactory = css::script::InvocationAdapterFactory::create(ctx);
281 c->xIntrospection = theIntrospection::get(ctx);
283 Any a = ctx->getValueByName("/singletons/com.sun.star.reflection.theTypeDescriptionManager");
284 a >>= c->xTdMgr;
285 if( ! c->xTdMgr.is() )
286 throw RuntimeException( "pyuno: couldn't retrieve typedescriptionmanager" );
288 me->cargo =c;
289 return PyRef( reinterpret_cast< PyObject * > ( me ), SAL_NO_ACQUIRE );
292 void stRuntimeImpl::del(PyObject* self)
294 RuntimeImpl *me = reinterpret_cast< RuntimeImpl * > ( self );
295 if( me->cargo->logFile )
296 fclose( me->cargo->logFile );
297 delete me->cargo;
298 PyObject_Del (self);
302 void Runtime::initialize( const Reference< XComponentContext > & ctx )
303 throw ( RuntimeException, std::exception )
305 PyRef globalDict, runtime;
306 getRuntimeImpl( globalDict , runtime );
307 RuntimeImpl *impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
309 if( runtime.is() && impl->cargo->valid )
311 throw RuntimeException("pyuno runtime has already been initialized before" );
313 PyRef keep( RuntimeImpl::create( ctx ) );
314 PyDict_SetItemString( globalDict.get(), "pyuno_runtime" , keep.get() );
315 Py_XINCREF( keep.get() );
319 bool Runtime::isInitialized() throw ( RuntimeException )
321 PyRef globalDict, runtime;
322 getRuntimeImpl( globalDict , runtime );
323 RuntimeImpl *impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
324 return runtime.is() && impl->cargo->valid;
327 Runtime::Runtime() throw( RuntimeException )
328 : impl( nullptr )
330 PyRef globalDict, runtime;
331 getRuntimeImpl( globalDict , runtime );
332 if( ! runtime.is() )
334 throw RuntimeException(
335 "pyuno runtime is not initialized, "
336 "(the pyuno.bootstrap needs to be called before using any uno classes)" );
338 impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
339 Py_XINCREF( runtime.get() );
342 Runtime::Runtime( const Runtime & r )
344 impl = r.impl;
345 Py_XINCREF( reinterpret_cast< PyObject * >(impl) );
348 Runtime::~Runtime()
350 Py_XDECREF( reinterpret_cast< PyObject * >(impl) );
353 Runtime & Runtime::operator = ( const Runtime & r )
355 PyRef temp( reinterpret_cast< PyObject * >(r.impl) );
356 Py_XINCREF( temp.get() );
357 Py_XDECREF( reinterpret_cast< PyObject * >(impl) );
358 impl = r.impl;
359 return *this;
362 PyRef Runtime::any2PyObject (const Any &a ) const
363 throw ( css::script::CannotConvertException,
364 css::lang::IllegalArgumentException,
365 RuntimeException)
367 if( ! impl->cargo->valid )
369 throw RuntimeException("pyuno runtime must be initialized before calling any2PyObject" );
372 switch (a.getValueTypeClass ())
374 case typelib_TypeClass_VOID:
376 Py_INCREF (Py_None);
377 return PyRef(Py_None);
379 case typelib_TypeClass_CHAR:
381 sal_Unicode c = *static_cast<sal_Unicode const *>(a.getValue());
382 return PyRef( PyUNO_char_new( c , *this ), SAL_NO_ACQUIRE );
384 case typelib_TypeClass_BOOLEAN:
386 bool b;
387 if ((a >>= b) && b)
388 return Py_True;
389 else
390 return Py_False;
392 case typelib_TypeClass_BYTE:
393 case typelib_TypeClass_SHORT:
394 case typelib_TypeClass_UNSIGNED_SHORT:
395 case typelib_TypeClass_LONG:
397 sal_Int32 l = 0;
398 a >>= l;
399 return PyRef( PyLong_FromLong (l), SAL_NO_ACQUIRE );
401 case typelib_TypeClass_UNSIGNED_LONG:
403 sal_uInt32 l = 0;
404 a >>= l;
405 return PyRef( PyLong_FromUnsignedLong (l), SAL_NO_ACQUIRE );
407 case typelib_TypeClass_HYPER:
409 sal_Int64 l = 0;
410 a >>= l;
411 return PyRef( PyLong_FromLongLong (l), SAL_NO_ACQUIRE);
413 case typelib_TypeClass_UNSIGNED_HYPER:
415 sal_uInt64 l = 0;
416 a >>= l;
417 return PyRef( PyLong_FromUnsignedLongLong (l), SAL_NO_ACQUIRE);
419 case typelib_TypeClass_FLOAT:
421 float f = 0.0;
422 a >>= f;
423 return PyRef(PyFloat_FromDouble (f), SAL_NO_ACQUIRE);
425 case typelib_TypeClass_DOUBLE:
427 double d = 0.0;
428 a >>= d;
429 return PyRef( PyFloat_FromDouble (d), SAL_NO_ACQUIRE);
431 case typelib_TypeClass_STRING:
433 OUString tmp_ostr;
434 a >>= tmp_ostr;
435 return ustring2PyUnicode( tmp_ostr );
437 case typelib_TypeClass_TYPE:
439 Type t;
440 a >>= t;
441 OString o = OUStringToOString( t.getTypeName(), RTL_TEXTENCODING_ASCII_US );
442 return PyRef(
443 PyUNO_Type_new (
444 o.getStr(), (css::uno::TypeClass)t.getTypeClass(), *this),
445 SAL_NO_ACQUIRE);
447 case typelib_TypeClass_ANY:
449 //I don't think this can happen.
450 Py_INCREF (Py_None);
451 return Py_None;
453 case typelib_TypeClass_ENUM:
455 sal_Int32 l = *static_cast<sal_Int32 const *>(a.getValue());
456 TypeDescription desc( a.getValueType() );
457 if( desc.is() )
459 desc.makeComplete();
460 typelib_EnumTypeDescription *pEnumDesc =
461 reinterpret_cast<typelib_EnumTypeDescription *>(desc.get());
462 for( int i = 0 ; i < pEnumDesc->nEnumValues ; i ++ )
464 if( pEnumDesc->pEnumValues[i] == l )
466 OString v = OUStringToOString( pEnumDesc->ppEnumNames[i], RTL_TEXTENCODING_ASCII_US);
467 OString e = OUStringToOString( pEnumDesc->aBase.pTypeName, RTL_TEXTENCODING_ASCII_US);
468 return PyRef( PyUNO_Enum_new(e.getStr(),v.getStr(), *this ), SAL_NO_ACQUIRE );
472 OUStringBuffer buf;
473 buf.append( "Any carries enum " );
474 buf.append( a.getValueType().getTypeName());
475 buf.append( " with invalid value " ).append( l );
476 throw RuntimeException( buf.makeStringAndClear() );
478 case typelib_TypeClass_EXCEPTION:
479 case typelib_TypeClass_STRUCT:
481 PyRef excClass = getClass( a.getValueType().getTypeName(), *this );
482 PyRef value = PyUNOStruct_new( a, getImpl()->cargo->xInvocation );
483 PyRef argsTuple( PyTuple_New( 1 ) , SAL_NO_ACQUIRE, NOT_NULL );
484 PyTuple_SetItem( argsTuple.get() , 0 , value.getAcquired() );
485 PyRef ret( PyObject_CallObject( excClass.get() , argsTuple.get() ), SAL_NO_ACQUIRE );
486 if( ! ret.is() )
488 OUStringBuffer buf;
489 buf.append( "Couldn't instantiate python representation of structured UNO type " );
490 buf.append( a.getValueType().getTypeName() );
491 throw RuntimeException( buf.makeStringAndClear() );
494 if( css::uno::TypeClass_EXCEPTION == a.getValueTypeClass() )
496 // add the message in a standard python way !
497 PyRef args( PyTuple_New( 1 ), SAL_NO_ACQUIRE, NOT_NULL );
499 // assuming that the Message is always the first member, wuuuu
500 void const *pData = a.getValue();
501 OUString message = *static_cast<OUString const *>(pData);
502 PyRef pymsg = ustring2PyString( message );
503 PyTuple_SetItem( args.get(), 0 , pymsg.getAcquired() );
504 // the exception base functions want to have an "args" tuple,
505 // which contains the message
506 PyObject_SetAttrString( ret.get(), "args", args.get() );
508 return ret;
510 case typelib_TypeClass_SEQUENCE:
512 Sequence<Any> s;
514 Sequence< sal_Int8 > byteSequence;
515 if( a >>= byteSequence )
517 // byte sequence is treated in a special way because of peformance reasons
518 // @since 0.9.2
519 return PyRef( PyUNO_ByteSequence_new( byteSequence, *this ), SAL_NO_ACQUIRE );
521 else
523 Reference< XTypeConverter > tc = getImpl()->cargo->xTypeConverter;
524 Reference< XSingleServiceFactory > ssf = getImpl()->cargo->xInvocation;
525 tc->convertTo (a, cppu::UnoType<decltype(s)>::get()) >>= s;
526 PyRef tuple( PyTuple_New (s.getLength()), SAL_NO_ACQUIRE, NOT_NULL);
527 int i=0;
530 for ( i = 0; i < s.getLength (); i++)
532 PyRef element;
533 element = any2PyObject (tc->convertTo (s[i], s[i].getValueType() ));
534 OSL_ASSERT( element.is() );
535 PyTuple_SetItem( tuple.get(), i, element.getAcquired() );
538 catch( css::uno::Exception & )
540 for( ; i < s.getLength() ; i ++ )
542 Py_INCREF( Py_None );
543 PyTuple_SetItem( tuple.get(), i, Py_None );
545 throw;
547 return tuple;
550 case typelib_TypeClass_INTERFACE:
552 Reference<XInterface> tmp_interface;
553 a >>= tmp_interface;
554 if (!tmp_interface.is ())
555 return Py_None;
557 return PyUNO_new( a, getImpl()->cargo->xInvocation );
559 default:
561 OUStringBuffer buf;
562 buf.append( "Unknown UNO type class " );
563 buf.append( (sal_Int32 ) a.getValueTypeClass() );
564 throw RuntimeException(buf.makeStringAndClear( ) );
569 static Sequence< Type > invokeGetTypes( const Runtime & r , PyObject * o )
571 Sequence< Type > ret;
573 PyRef method( PyObject_GetAttrString( o , "getTypes" ), SAL_NO_ACQUIRE );
574 raiseInvocationTargetExceptionWhenNeeded( r );
575 if( method.is() && PyCallable_Check( method.get() ) )
577 PyRef types( PyObject_CallObject( method.get(), nullptr ) , SAL_NO_ACQUIRE );
578 raiseInvocationTargetExceptionWhenNeeded( r );
579 if( types.is() && PyTuple_Check( types.get() ) )
581 int size = PyTuple_Size( types.get() );
583 // add the XUnoTunnel interface for uno object identity concept (hack)
584 ret.realloc( size + 1 );
585 for( int i = 0 ; i < size ; i ++ )
587 Any a = r.pyObject2Any(PyTuple_GetItem(types.get(),i));
588 a >>= ret[i];
590 ret[size] = cppu::UnoType<css::lang::XUnoTunnel>::get();
593 return ret;
596 static OUString
597 lcl_ExceptionMessage(PyObject *const o, OUString const*const pWrapped)
599 OUStringBuffer buf;
600 buf.append("Couldn't convert ");
601 PyRef reprString( PyObject_Str(o), SAL_NO_ACQUIRE );
602 buf.appendAscii( PyStr_AsString(reprString.get()) );
603 buf.append(" to a UNO type");
604 if (pWrapped)
606 buf.append("; caught exception: ");
607 buf.append(*pWrapped);
609 return buf.makeStringAndClear();
612 // For Python 2.7 - see https://bugs.python.org/issue24161
613 // Fills aSeq and returns true if pObj is a valid iterator
614 bool Runtime::pyIterUnpack( PyObject *const pObj, Any &a ) const
616 if( !PyIter_Check( pObj ))
617 return false;
619 PyObject *pItem = PyIter_Next( pObj );
620 if( !pItem )
622 if( PyErr_Occurred() )
624 PyErr_Clear();
625 return false;
627 return true;
630 ::std::list<Any> items;
633 PyRef rItem( pItem, SAL_NO_ACQUIRE );
634 items.push_back( pyObject2Any( rItem.get() ) );
636 while( (pItem = PyIter_Next( pObj )) );
637 a <<= comphelper::containerToSequence<Any>(items);
638 return true;
641 Any Runtime::pyObject2Any ( const PyRef & source, enum ConversionMode mode ) const
642 throw ( css::uno::RuntimeException )
644 if( ! impl->cargo->valid )
646 throw RuntimeException("pyuno runtime must be initialized before calling any2PyObject" );
649 Any a;
650 PyObject *o = source.get();
651 if( Py_None == o )
655 // In Python 3, there is no PyInt type.
656 #if PY_MAJOR_VERSION < 3
657 else if (PyInt_Check (o))
659 if( o == Py_True )
661 a <<= true;
663 else if ( o == Py_False )
665 a <<= false;
667 else
669 sal_Int32 l = (sal_Int32) PyLong_AsLong( o );
670 if( l < 128 && l >= -128 )
672 sal_Int8 b = (sal_Int8 ) l;
673 a <<= b;
675 else if( l <= 0x7fff && l >= -0x8000 )
677 sal_Int16 s = (sal_Int16) l;
678 a <<= s;
680 else
682 a <<= l;
686 #endif /* PY_MAJOR_VERSION < 3 */
687 else if (PyLong_Check (o))
689 #if PY_MAJOR_VERSION >= 3
690 // Convert the Python 3 booleans that are actually of type PyLong.
691 if(o == Py_True)
693 a <<= true;
695 else if(o == Py_False)
697 a <<= false;
699 else
701 #endif /* PY_MAJOR_VERSION >= 3 */
702 sal_Int64 l = (sal_Int64)PyLong_AsLong (o);
703 if( l < 128 && l >= -128 )
705 sal_Int8 b = (sal_Int8 ) l;
706 a <<= b;
708 else if( l <= 0x7fff && l >= -0x8000 )
710 sal_Int16 s = (sal_Int16) l;
711 a <<= s;
713 else if( l <= SAL_CONST_INT64(0x7fffffff) &&
714 l >= -SAL_CONST_INT64(0x80000000) )
716 sal_Int32 l32 = (sal_Int32) l;
717 a <<= l32;
719 else
721 a <<= l;
723 #if PY_MAJOR_VERSION >= 3
725 #endif
727 else if (PyFloat_Check (o))
729 double d = PyFloat_AsDouble (o);
730 a <<= d;
732 else if (PyStrBytes_Check(o) || PyUnicode_Check(o))
734 a <<= pyString2ustring(o);
736 else if (PyTuple_Check (o))
738 Sequence<Any> s (PyTuple_Size (o));
739 for (Py_ssize_t i = 0; i < PyTuple_Size (o); i++)
741 s[i] = pyObject2Any (PyTuple_GetItem (o, i), mode );
743 a <<= s;
745 else if (PyList_Check (o))
747 Py_ssize_t l = PyList_Size (o);
748 Sequence<Any> s (l);
749 for (Py_ssize_t i = 0; i < l; i++)
751 s[i] = pyObject2Any (PyList_GetItem (o, i), mode );
753 a <<= s;
755 else if (!pyIterUnpack (o, a))
757 Runtime runtime;
758 // should be removed, in case ByteSequence gets derived from String
759 if( PyObject_IsInstance( o, getByteSequenceClass( runtime ).get() ) )
761 PyRef str(PyObject_GetAttrString( o , "value" ),SAL_NO_ACQUIRE);
762 Sequence< sal_Int8 > seq;
763 if( PyStrBytes_Check( str.get() ) )
765 seq = Sequence<sal_Int8 > (
766 reinterpret_cast<sal_Int8*>(PyStrBytes_AsString(str.get())), PyStrBytes_Size(str.get()));
768 a <<= seq;
770 else
771 if( PyObject_IsInstance( o, getTypeClass( runtime ).get() ) )
773 Type t = PyType2Type( o );
774 a <<= t;
776 else if( PyObject_IsInstance( o, getEnumClass( runtime ).get() ) )
778 a = PyEnum2Enum( o );
780 else if( isInstanceOfStructOrException( o ) )
782 PyRef struc(PyObject_GetAttrString( o , "value" ),SAL_NO_ACQUIRE);
783 PyUNO * obj = reinterpret_cast<PyUNO*>(struc.get());
784 Reference< XMaterialHolder > holder( obj->members->xInvocation, UNO_QUERY );
785 if( holder.is( ) )
786 a = holder->getMaterial();
787 else
789 throw RuntimeException(
790 "struct or exception wrapper does not support XMaterialHolder" );
793 else if( PyObject_IsInstance( o, getPyUnoClass().get() ) )
795 PyUNO* o_pi = reinterpret_cast<PyUNO*>(o);
796 a = o_pi->members->wrappedObject;
798 else if( PyObject_IsInstance( o, getPyUnoStructClass().get() ) )
800 PyUNO* o_pi = reinterpret_cast<PyUNO*>(o);
801 Reference<XMaterialHolder> my_mh (o_pi->members->xInvocation, UNO_QUERY);
803 if (!my_mh.is())
805 throw RuntimeException(
806 "struct wrapper does not support XMaterialHolder" );
808 else
809 a = my_mh->getMaterial();
811 else if( PyObject_IsInstance( o, getCharClass( runtime ).get() ) )
813 sal_Unicode c = PyChar2Unicode( o );
814 a.setValue( &c, cppu::UnoType<cppu::UnoCharType>::get());
816 else if( PyObject_IsInstance( o, getAnyClass( runtime ).get() ) )
818 if( ACCEPT_UNO_ANY == mode )
820 a = pyObject2Any( PyRef( PyObject_GetAttrString( o , "value" ), SAL_NO_ACQUIRE) );
821 Type t;
822 pyObject2Any( PyRef( PyObject_GetAttrString( o, "type" ), SAL_NO_ACQUIRE ) ) >>= t;
826 a = getImpl()->cargo->xTypeConverter->convertTo( a, t );
828 catch( const css::uno::Exception & e )
830 throw WrappedTargetRuntimeException(
831 e.Message, e.Context, makeAny(e));
834 else
836 throw RuntimeException(
837 "uno.Any instance not accepted during method call, "
838 "use uno.invoke instead" );
841 else
843 Reference< XInterface > mappedObject;
844 Reference< XInvocation > adapterObject;
846 // instance already mapped out to the world ?
847 PyRef2Adapter::iterator ii = impl->cargo->mappedObjects.find( PyRef( o ) );
848 if( ii != impl->cargo->mappedObjects.end() )
850 adapterObject = ii->second;
853 if( adapterObject.is() )
855 // object got already bridged !
856 Reference< css::lang::XUnoTunnel > tunnel( adapterObject, UNO_QUERY );
858 Adapter *pAdapter = reinterpret_cast<Adapter*>(
859 tunnel->getSomething(
860 ::pyuno::Adapter::getUnoTunnelImplementationId() ) );
862 mappedObject = impl->cargo->xAdapterFactory->createAdapter(
863 adapterObject, pAdapter->getWrappedTypes() );
865 else
867 try {
868 Sequence<Type> interfaces = invokeGetTypes(*this, o);
869 if (interfaces.getLength())
871 Adapter *pAdapter = new Adapter( o, interfaces );
872 mappedObject =
873 getImpl()->cargo->xAdapterFactory->createAdapter(
874 pAdapter, interfaces );
876 // keep a list of exported objects to ensure object identity !
877 impl->cargo->mappedObjects[ PyRef(o) ] =
878 css::uno::WeakReference< XInvocation > ( pAdapter );
880 } catch (InvocationTargetException const& e) {
881 OUString const msg(lcl_ExceptionMessage(o, &e.Message));
882 throw WrappedTargetRuntimeException( // re-wrap that
883 msg, e.Context, e.TargetException);
886 if( mappedObject.is() )
888 a = css::uno::makeAny( mappedObject );
890 else
892 OUString const msg(lcl_ExceptionMessage(o, nullptr));
893 throw RuntimeException(msg);
897 return a;
900 Any Runtime::extractUnoException( const PyRef & excType, const PyRef &excValue, const PyRef &excTraceback) const
902 OUString str;
903 Any ret;
904 if( excTraceback.is() )
906 Exception e;
907 PyRef unoModule;
908 if ( impl )
912 unoModule = impl->cargo->getUnoModule();
914 catch (const Exception &ei)
916 e=ei;
919 if( unoModule.is() )
921 PyRef extractTraceback(
922 PyDict_GetItemString(unoModule.get(),"_uno_extract_printable_stacktrace" ) );
924 if( PyCallable_Check(extractTraceback.get()) )
926 PyRef args( PyTuple_New( 1), SAL_NO_ACQUIRE, NOT_NULL );
927 PyTuple_SetItem( args.get(), 0, excTraceback.getAcquired() );
928 PyRef pyStr( PyObject_CallObject( extractTraceback.get(),args.get() ), SAL_NO_ACQUIRE);
929 str = OUString::createFromAscii( PyStr_AsString(pyStr.get()) );
931 else
933 str = "Couldn't find uno._uno_extract_printable_stacktrace";
936 else
938 str = "Could not load uno.py, no stacktrace available";
939 if ( !e.Message.isEmpty() )
941 str += " (Error loading uno.py: " + e.Message + ")";
946 else
948 // it may occur, that no traceback is given (e.g. only native code below)
949 str = "no traceback available";
952 if( isInstanceOfStructOrException( excValue.get() ) )
954 ret = pyObject2Any( excValue );
956 else
958 OUStringBuffer buf;
959 PyRef typeName( PyObject_Str( excType.get() ), SAL_NO_ACQUIRE );
960 if( typeName.is() )
962 buf.appendAscii( PyStr_AsString( typeName.get() ) );
964 else
966 buf.append( "no typename available" );
968 buf.append( ": " );
969 PyRef valueRep( PyObject_Str( excValue.get() ), SAL_NO_ACQUIRE );
970 if( valueRep.is() )
972 buf.appendAscii( PyStr_AsString( valueRep.get()));
974 else
976 buf.append( "Couldn't convert exception value to a string" );
978 buf.append( ", traceback follows\n" );
979 if( !str.isEmpty() )
981 buf.append( str );
982 buf.append( "\n" );
984 else
986 buf.append( ", no traceback available\n" );
988 RuntimeException e;
989 e.Message = buf.makeStringAndClear();
990 #if OSL_DEBUG_LEVEL > 0
991 fprintf( stderr, "Python exception: %s\n",
992 OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr() );
993 #endif
994 ret = css::uno::makeAny( e );
996 return ret;
1000 PyThreadAttach::PyThreadAttach( PyInterpreterState *interp)
1001 throw ( css::uno::RuntimeException )
1003 tstate = PyThreadState_New( interp );
1004 if( !tstate )
1005 throw RuntimeException( "Couldn't create a pythreadstate" );
1006 PyEval_AcquireThread( tstate);
1009 PyThreadAttach::~PyThreadAttach()
1011 PyThreadState_Clear( tstate );
1012 PyEval_ReleaseThread( tstate );
1013 PyThreadState_Delete( tstate );
1016 PyThreadDetach::PyThreadDetach() throw ( css::uno::RuntimeException )
1018 tstate = PyThreadState_Get();
1019 PyEval_ReleaseThread( tstate );
1022 /** Acquires the global interpreter lock again
1025 PyThreadDetach::~PyThreadDetach()
1027 PyEval_AcquireThread( tstate );
1031 PyRef RuntimeCargo::getUnoModule()
1033 if( ! dictUnoModule.is() )
1035 dictUnoModule = importUnoModule();
1037 return dictUnoModule;
1041 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */