android: Update app icon to new startcenter icon
[LibreOffice.git] / pyuno / source / module / pyuno_runtime.cxx
blob7f3eb7a6e95f39e665db618d8929ad2218ddc5b1
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_folders.h>
22 #include "pyuno_impl.hxx"
24 #include <o3tl/any.hxx>
25 #include <osl/diagnose.h>
26 #include <osl/thread.h>
27 #include <osl/module.h>
28 #include <osl/process.h>
29 #include <rtl/ustrbuf.hxx>
30 #include <rtl/bootstrap.hxx>
31 #include <rtl/ref.hxx>
33 #include <typelib/typedescription.hxx>
35 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
36 #include <com/sun/star/beans/XMaterialHolder.hpp>
37 #include <com/sun/star/beans/theIntrospection.hpp>
38 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
39 #include <com/sun/star/script/Converter.hpp>
40 #include <com/sun/star/script/InvocationAdapterFactory.hpp>
41 #include <com/sun/star/script/XInvocation2.hpp>
42 #include <com/sun/star/reflection/theCoreReflection.hpp>
43 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
44 #include <comphelper/sequence.hxx>
45 #include <comphelper/servicehelper.hxx>
46 #include <cppuhelper/exc_hlp.hxx>
48 #include <vector>
50 using com::sun::star::uno::Reference;
51 using com::sun::star::uno::XInterface;
52 using com::sun::star::uno::Any;
53 using com::sun::star::uno::TypeDescription;
54 using com::sun::star::uno::Sequence;
55 using com::sun::star::uno::Type;
56 using com::sun::star::uno::UNO_QUERY;
57 using com::sun::star::uno::Exception;
58 using com::sun::star::uno::RuntimeException;
59 using com::sun::star::uno::XComponentContext;
60 using com::sun::star::lang::WrappedTargetRuntimeException;
61 using com::sun::star::lang::XSingleServiceFactory;
62 using com::sun::star::lang::XUnoTunnel;
63 using com::sun::star::reflection::theCoreReflection;
64 using com::sun::star::reflection::InvocationTargetException;
65 using com::sun::star::script::Converter;
66 using com::sun::star::script::XTypeConverter;
67 using com::sun::star::script::XInvocation;
68 using com::sun::star::beans::XMaterialHolder;
69 using com::sun::star::beans::theIntrospection;
71 namespace pyuno
74 static PyTypeObject RuntimeImpl_Type =
76 PyVarObject_HEAD_INIT (&PyType_Type, 0)
77 "pyuno_runtime",
78 sizeof (RuntimeImpl),
80 RuntimeImpl::del,
81 #if PY_VERSION_HEX >= 0x03080000
82 0, // Py_ssize_t tp_vectorcall_offset
83 #else
84 nullptr, // printfunc tp_print
85 #endif
86 nullptr,
87 nullptr,
88 nullptr,
89 nullptr,
90 nullptr,
91 nullptr,
92 nullptr,
93 nullptr,
94 nullptr,
95 nullptr,
96 nullptr,
97 nullptr,
98 nullptr,
100 nullptr,
101 nullptr,
102 nullptr,
103 nullptr,
105 nullptr,
106 nullptr,
107 nullptr,
108 nullptr,
109 nullptr,
110 nullptr,
111 nullptr,
112 nullptr,
113 nullptr,
115 nullptr,
116 nullptr,
117 nullptr,
118 nullptr,
119 nullptr,
120 nullptr,
121 nullptr,
122 nullptr,
123 nullptr,
124 nullptr,
125 nullptr
127 #if PY_VERSION_HEX >= 0x03040000
128 , nullptr
129 #if PY_VERSION_HEX >= 0x03080000
130 , nullptr // vectorcallfunc tp_vectorcall
131 #if PY_VERSION_HEX < 0x03090000
132 #if defined __clang__
133 #pragma clang diagnostic push
134 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
135 #endif
136 , nullptr // tp_print
137 #if defined __clang__
138 #pragma clang diagnostic pop
139 #endif
140 #endif
141 #endif
142 #endif
145 /*----------------------------------------------------------------------
146 Runtime implementation
147 -----------------------------------------------------------------------*/
148 /// @throws css::uno::RuntimeException
149 static void getRuntimeImpl( PyRef & globalDict, PyRef &runtimeImpl )
151 PyThreadState * state = PyThreadState_Get();
152 if( ! state )
154 throw RuntimeException( "python global interpreter must be held (thread must be attached)" );
157 PyObject* pModule = PyImport_AddModule("__main__");
159 if (!pModule)
161 throw RuntimeException("can't import __main__ module");
164 globalDict = PyRef( PyModule_GetDict(pModule));
166 if( ! globalDict.is() ) // FATAL !
168 throw RuntimeException("can't find __main__ module");
170 runtimeImpl = PyDict_GetItemString( globalDict.get() , "pyuno_runtime" );
173 /// @throws RuntimeException
174 static PyRef importUnoModule( )
176 // import the uno module
177 PyRef module( PyImport_ImportModule( "uno" ), SAL_NO_ACQUIRE, NOT_NULL );
178 if( PyErr_Occurred() )
180 PyRef excType, excValue, excTraceback;
181 PyErr_Fetch( reinterpret_cast<PyObject **>(&excType), reinterpret_cast<PyObject**>(&excValue), reinterpret_cast<PyObject**>(&excTraceback));
182 // As of Python 2.7 this gives a rather non-useful "<traceback object at 0xADDRESS>",
183 // but it is the best we can do in the absence of uno._uno_extract_printable_stacktrace
184 // Who knows, a future Python might print something better.
185 PyRef str( PyObject_Str( excTraceback.get() ), SAL_NO_ACQUIRE );
187 OUStringBuffer buf;
188 buf.append( "python object raised an unknown exception (" );
189 PyRef valueRep( PyObject_Repr( excValue.get() ), SAL_NO_ACQUIRE );
190 buf.appendAscii( PyUnicode_AsUTF8( valueRep.get())).append( ", traceback follows\n" );
191 buf.appendAscii( PyUnicode_AsUTF8( str.get() ) );
192 buf.append( ")" );
193 throw RuntimeException( buf.makeStringAndClear() );
195 PyRef dict( PyModule_GetDict( module.get() ) );
196 return dict;
199 static void readLoggingConfig( sal_Int32 *pLevel, FILE **ppFile )
201 *pLevel = LogLevel::NONE;
202 *ppFile = nullptr;
203 OUString fileName;
204 osl_getModuleURLFromFunctionAddress(
205 reinterpret_cast< oslGenericFunction >(readLoggingConfig),
206 &fileName.pData );
207 fileName = fileName.copy( fileName.lastIndexOf( '/' )+1 );
208 #ifdef MACOSX
209 fileName += "../" LIBO_ETC_FOLDER "/";
210 #endif
211 fileName += SAL_CONFIGFILE("pyuno" );
212 rtl::Bootstrap bootstrapHandle( fileName );
214 OUString str;
215 if( bootstrapHandle.getFrom( "PYUNO_LOGLEVEL", str ) )
217 if ( str == "NONE" )
218 *pLevel = LogLevel::NONE;
219 else if ( str == "CALL" )
220 *pLevel = LogLevel::CALL;
221 else if ( str == "ARGS" )
222 *pLevel = LogLevel::ARGS;
223 else
225 fprintf( stderr, "unknown loglevel %s\n",
226 OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
229 if( *pLevel <= LogLevel::NONE )
230 return;
232 *ppFile = stdout;
233 if( !bootstrapHandle.getFrom( "PYUNO_LOGTARGET", str ) )
234 return;
236 if ( str == "stdout" )
237 *ppFile = stdout;
238 else if ( str == "stderr" )
239 *ppFile = stderr;
240 else
242 oslProcessInfo data;
243 data.Size = sizeof( data );
244 osl_getProcessInfo(
245 nullptr , osl_Process_IDENTIFIER , &data );
246 osl_getSystemPathFromFileURL( str.pData, &str.pData);
247 OString o = OUStringToOString( str, osl_getThreadTextEncoding() );
248 o += ".";
249 o += OString::number( data.Ident );
251 *ppFile = fopen( o.getStr() , "w" );
252 if ( *ppFile )
254 // do not buffer (useful if e.g. analyzing a crash)
255 setvbuf( *ppFile, nullptr, _IONBF, 0 );
257 else
259 fprintf( stderr, "couldn't create file %s\n",
260 OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
266 /*-------------------------------------------------------------------
267 RuntimeImpl implementations
268 *-------------------------------------------------------------------*/
269 PyRef stRuntimeImpl::create( const Reference< XComponentContext > &ctx )
271 RuntimeImpl *me = PyObject_New (RuntimeImpl, &RuntimeImpl_Type);
272 if( ! me )
273 throw RuntimeException( "cannot instantiate pyuno::RuntimeImpl" );
274 me->cargo = nullptr;
275 // must use a different struct here, as the PyObject_New
276 // makes C++ unusable
277 RuntimeCargo *c = new RuntimeCargo;
278 readLoggingConfig( &(c->logLevel) , &(c->logFile) );
279 log( c, LogLevel::CALL, "Instantiating pyuno bridge" );
281 c->valid = true;
282 c->xContext = ctx;
283 c->xInvocation = Reference< XSingleServiceFactory > (
284 ctx->getServiceManager()->createInstanceWithContext(
285 "com.sun.star.script.Invocation",
286 ctx ),
287 css::uno::UNO_QUERY_THROW );
289 c->xTypeConverter = Converter::create(ctx);
290 if( ! c->xTypeConverter.is() )
291 throw RuntimeException( "pyuno: couldn't instantiate typeconverter service" );
293 c->xCoreReflection = theCoreReflection::get(ctx);
295 c->xAdapterFactory = css::script::InvocationAdapterFactory::create(ctx);
297 c->xIntrospection = theIntrospection::get(ctx);
299 Any a = ctx->getValueByName("/singletons/com.sun.star.reflection.theTypeDescriptionManager");
300 a >>= c->xTdMgr;
301 if( ! c->xTdMgr.is() )
302 throw RuntimeException( "pyuno: couldn't retrieve typedescriptionmanager" );
304 me->cargo =c;
305 return PyRef( reinterpret_cast< PyObject * > ( me ), SAL_NO_ACQUIRE );
308 void stRuntimeImpl::del(PyObject* self)
310 RuntimeImpl *me = reinterpret_cast< RuntimeImpl * > ( self );
311 if( me->cargo->logFile )
312 fclose( me->cargo->logFile );
313 delete me->cargo;
314 PyObject_Del (self);
318 void Runtime::initialize( const Reference< XComponentContext > & ctx )
320 PyRef globalDict, runtime;
321 getRuntimeImpl( globalDict , runtime );
322 RuntimeImpl *impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
324 if( runtime.is() && impl->cargo->valid )
326 throw RuntimeException("pyuno runtime has already been initialized before" );
328 PyRef keep( RuntimeImpl::create( ctx ) );
329 PyDict_SetItemString( globalDict.get(), "pyuno_runtime" , keep.get() );
330 Py_XINCREF( keep.get() );
334 bool Runtime::isInitialized()
336 PyRef globalDict, runtime;
337 getRuntimeImpl( globalDict , runtime );
338 RuntimeImpl *impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
339 return runtime.is() && impl->cargo->valid;
342 Runtime::Runtime()
343 : impl( nullptr )
345 PyRef globalDict, runtime;
346 getRuntimeImpl( globalDict , runtime );
347 if( ! runtime.is() )
349 throw RuntimeException(
350 "pyuno runtime is not initialized, "
351 "(the pyuno.bootstrap needs to be called before using any uno classes)" );
353 impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
354 Py_XINCREF( runtime.get() );
357 Runtime::Runtime( const Runtime & r )
359 impl = r.impl;
360 Py_XINCREF( reinterpret_cast< PyObject * >(impl) );
363 Runtime::~Runtime()
365 Py_XDECREF( reinterpret_cast< PyObject * >(impl) );
368 Runtime & Runtime::operator = ( const Runtime & r )
370 PyRef temp( reinterpret_cast< PyObject * >(r.impl) );
371 Py_XINCREF( temp.get() );
372 Py_XDECREF( reinterpret_cast< PyObject * >(impl) );
373 impl = r.impl;
374 return *this;
377 PyRef Runtime::any2PyObject (const Any &a ) const
379 if( ! impl->cargo->valid )
381 throw RuntimeException("pyuno runtime must be initialized before calling any2PyObject" );
384 switch (a.getValueTypeClass ())
386 case css::uno::TypeClass_VOID:
388 Py_INCREF (Py_None);
389 return PyRef(Py_None);
391 case css::uno::TypeClass_CHAR:
393 sal_Unicode c = *o3tl::forceAccess<sal_Unicode>(a);
394 return PyRef( PyUNO_char_new( c , *this ), SAL_NO_ACQUIRE );
396 case css::uno::TypeClass_BOOLEAN:
398 bool b;
399 if ((a >>= b) && b)
400 return Py_True;
401 else
402 return Py_False;
404 case css::uno::TypeClass_BYTE:
405 case css::uno::TypeClass_SHORT:
406 case css::uno::TypeClass_UNSIGNED_SHORT:
407 case css::uno::TypeClass_LONG:
409 sal_Int32 l = 0;
410 a >>= l;
411 return PyRef( PyLong_FromLong (l), SAL_NO_ACQUIRE );
413 case css::uno::TypeClass_UNSIGNED_LONG:
415 sal_uInt32 l = 0;
416 a >>= l;
417 return PyRef( PyLong_FromUnsignedLong (l), SAL_NO_ACQUIRE );
419 case css::uno::TypeClass_HYPER:
421 sal_Int64 l = 0;
422 a >>= l;
423 return PyRef( PyLong_FromLongLong (l), SAL_NO_ACQUIRE);
425 case css::uno::TypeClass_UNSIGNED_HYPER:
427 sal_uInt64 l = 0;
428 a >>= l;
429 return PyRef( PyLong_FromUnsignedLongLong (l), SAL_NO_ACQUIRE);
431 case css::uno::TypeClass_FLOAT:
433 float f = 0.0;
434 a >>= f;
435 return PyRef(PyFloat_FromDouble (f), SAL_NO_ACQUIRE);
437 case css::uno::TypeClass_DOUBLE:
439 double d = 0.0;
440 a >>= d;
441 return PyRef( PyFloat_FromDouble (d), SAL_NO_ACQUIRE);
443 case css::uno::TypeClass_STRING:
445 OUString tmp_ostr;
446 a >>= tmp_ostr;
447 return ustring2PyUnicode( tmp_ostr );
449 case css::uno::TypeClass_TYPE:
451 Type t;
452 a >>= t;
453 OString o = OUStringToOString( t.getTypeName(), RTL_TEXTENCODING_ASCII_US );
454 return PyRef(
455 PyUNO_Type_new (
456 o.getStr(), t.getTypeClass(), *this),
457 SAL_NO_ACQUIRE);
459 case css::uno::TypeClass_ANY:
461 //I don't think this can happen.
462 Py_INCREF (Py_None);
463 return Py_None;
465 case css::uno::TypeClass_ENUM:
467 sal_Int32 l = *static_cast<sal_Int32 const *>(a.getValue());
468 TypeDescription desc( a.getValueType() );
469 if( desc.is() )
471 desc.makeComplete();
472 typelib_EnumTypeDescription *pEnumDesc =
473 reinterpret_cast<typelib_EnumTypeDescription *>(desc.get());
474 for( int i = 0 ; i < pEnumDesc->nEnumValues ; i ++ )
476 if( pEnumDesc->pEnumValues[i] == l )
478 OString v = OUStringToOString( OUString::unacquired(&pEnumDesc->ppEnumNames[i]), RTL_TEXTENCODING_ASCII_US);
479 OString e = OUStringToOString( OUString::unacquired(&pEnumDesc->aBase.pTypeName), RTL_TEXTENCODING_ASCII_US);
480 return PyRef( PyUNO_Enum_new(e.getStr(),v.getStr(), *this ), SAL_NO_ACQUIRE );
484 throw RuntimeException( "Any carries enum " + a.getValueType().getTypeName() +
485 " with invalid value " + OUString::number(l) );
487 case css::uno::TypeClass_EXCEPTION:
488 case css::uno::TypeClass_STRUCT:
490 PyRef excClass = getClass( a.getValueType().getTypeName(), *this );
491 PyRef value = PyUNOStruct_new( a, getImpl()->cargo->xInvocation );
492 PyRef argsTuple( PyTuple_New( 1 ) , SAL_NO_ACQUIRE, NOT_NULL );
493 PyTuple_SetItem( argsTuple.get() , 0 , value.getAcquired() );
494 PyRef ret( PyObject_CallObject( excClass.get() , argsTuple.get() ), SAL_NO_ACQUIRE );
495 if( ! ret.is() )
497 throw RuntimeException( "Couldn't instantiate python representation of structured UNO type " +
498 a.getValueType().getTypeName() );
501 if( auto e = o3tl::tryAccess<css::uno::Exception>(a) )
503 // add the message in a standard python way !
504 PyRef args( PyTuple_New( 1 ), SAL_NO_ACQUIRE, NOT_NULL );
506 PyRef pymsg = ustring2PyString( e->Message );
507 PyTuple_SetItem( args.get(), 0 , pymsg.getAcquired() );
508 // the exception base functions want to have an "args" tuple,
509 // which contains the message
510 PyObject_SetAttrString( ret.get(), "args", args.get() );
512 return ret;
514 case css::uno::TypeClass_SEQUENCE:
516 Sequence<Any> s;
518 Sequence< sal_Int8 > byteSequence;
519 if( a >>= byteSequence )
521 // byte sequence is treated in a special way because of performance reasons
522 // @since 0.9.2
523 return PyRef( PyUNO_ByteSequence_new( byteSequence, *this ), SAL_NO_ACQUIRE );
525 else
527 Reference< XTypeConverter > tc = getImpl()->cargo->xTypeConverter;
528 tc->convertTo (a, cppu::UnoType<decltype(s)>::get()) >>= s;
529 PyRef tuple( PyTuple_New (s.getLength()), SAL_NO_ACQUIRE, NOT_NULL);
530 int i=0;
533 for ( i = 0; i < s.getLength (); i++)
535 PyRef element = any2PyObject (tc->convertTo (s[i], s[i].getValueType() ));
536 OSL_ASSERT( element.is() );
537 PyTuple_SetItem( tuple.get(), i, element.getAcquired() );
540 catch( css::uno::Exception & )
542 for( ; i < s.getLength() ; i ++ )
544 Py_INCREF( Py_None );
545 PyTuple_SetItem( tuple.get(), i, Py_None );
547 throw;
549 return tuple;
552 case css::uno::TypeClass_INTERFACE:
554 Reference<XInterface> tmp_interface;
555 a >>= tmp_interface;
556 if (!tmp_interface.is ())
557 return Py_None;
559 return PyUNO_new( a, getImpl()->cargo->xInvocation );
561 default:
563 throw RuntimeException( "Unknown UNO type class " + OUString::number(static_cast<int>(a.getValueTypeClass())) );
568 static Sequence< Type > invokeGetTypes( const Runtime & r , PyObject * o )
570 Sequence< Type > ret;
572 PyRef method( PyObject_GetAttrString( o , "getTypes" ), SAL_NO_ACQUIRE );
573 raiseInvocationTargetExceptionWhenNeeded( r );
574 if( method.is() && PyCallable_Check( method.get() ) )
576 PyRef types( PyObject_CallObject( method.get(), nullptr ) , SAL_NO_ACQUIRE );
577 raiseInvocationTargetExceptionWhenNeeded( r );
578 if( types.is() && PyTuple_Check( types.get() ) )
580 int size = PyTuple_Size( types.get() );
582 // add the XUnoTunnel interface for uno object identity concept (hack)
583 ret.realloc( size + 1 );
584 auto pret = ret.getArray();
585 for( int i = 0 ; i < size ; i ++ )
587 Any a = r.pyObject2Any(PyTuple_GetItem(types.get(),i));
588 a >>= pret[i];
590 pret[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( PyUnicode_AsUTF8(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::vector<Any> items;
633 PyRef rItem( pItem, SAL_NO_ACQUIRE );
634 items.push_back( pyObject2Any( rItem.get() ) );
635 pItem = PyIter_Next( pObj );
637 while( pItem );
638 a <<= comphelper::containerToSequence(items);
639 return true;
642 Any Runtime::pyObject2Any(const PyRef & source, enum ConversionMode mode) const
644 if (!impl || !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 else if (PyLong_Check (o))
657 // Convert the Python 3 booleans that are actually of type PyLong.
658 if(o == Py_True)
660 a <<= true;
662 else if(o == Py_False)
664 a <<= false;
666 else
668 sal_Int64 l = static_cast<sal_Int64>(PyLong_AsLong (o));
669 if( l < 128 && l >= -128 )
671 sal_Int8 b = static_cast<sal_Int8>(l);
672 a <<= b;
674 else if( l <= 0x7fff && l >= -0x8000 )
676 sal_Int16 s = static_cast<sal_Int16>(l);
677 a <<= s;
679 else if( l <= SAL_CONST_INT64(0x7fffffff) &&
680 l >= -SAL_CONST_INT64(0x80000000) )
682 sal_Int32 l32 = static_cast<sal_Int32>(l);
683 a <<= l32;
685 else
687 a <<= l;
691 else if (PyFloat_Check (o))
693 double d = PyFloat_AsDouble (o);
694 a <<= d;
696 else if (PyBytes_Check(o) || PyUnicode_Check(o))
698 a <<= pyString2ustring(o);
700 else if (PyTuple_Check (o))
702 Sequence<Any> s (PyTuple_Size (o));
703 auto sRange = asNonConstRange(s);
704 for (Py_ssize_t i = 0; i < PyTuple_Size (o); i++)
706 sRange[i] = pyObject2Any (PyTuple_GetItem (o, i), mode );
708 a <<= s;
710 else if (PyList_Check (o))
712 Py_ssize_t l = PyList_Size (o);
713 Sequence<Any> s (l);
714 auto sRange = asNonConstRange(s);
715 for (Py_ssize_t i = 0; i < l; i++)
717 sRange[i] = pyObject2Any (PyList_GetItem (o, i), mode );
719 a <<= s;
721 else if (!pyIterUnpack (o, a))
723 Runtime runtime;
724 // should be removed, in case ByteSequence gets derived from String
725 if( PyObject_IsInstance( o, getByteSequenceClass( runtime ).get() ) )
727 PyRef str(PyObject_GetAttrString( o , "value" ),SAL_NO_ACQUIRE);
728 Sequence< sal_Int8 > seq;
729 if( PyBytes_Check( str.get() ) )
731 seq = Sequence<sal_Int8 > (
732 reinterpret_cast<sal_Int8*>(PyBytes_AsString(str.get())), PyBytes_Size(str.get()));
734 a <<= seq;
736 else
737 if( PyObject_IsInstance( o, getTypeClass( runtime ).get() ) )
739 Type t = PyType2Type( o );
740 a <<= t;
742 else if( PyObject_IsInstance( o, getEnumClass( runtime ).get() ) )
744 a = PyEnum2Enum( o );
746 else if( isInstanceOfStructOrException( o ) )
748 PyRef struc(PyObject_GetAttrString( o , "value" ),SAL_NO_ACQUIRE);
749 PyUNO * obj = reinterpret_cast<PyUNO*>(struc.get());
750 Reference< XMaterialHolder > holder( obj->members->xInvocation, UNO_QUERY );
751 if( !holder.is( ) )
753 throw RuntimeException(
754 "struct or exception wrapper does not support XMaterialHolder" );
757 a = holder->getMaterial();
760 else if( PyObject_IsInstance( o, getPyUnoClass().get() ) )
762 PyUNO* o_pi = reinterpret_cast<PyUNO*>(o);
763 a = o_pi->members->wrappedObject;
765 else if( PyObject_IsInstance( o, getPyUnoStructClass().get() ) )
767 PyUNO* o_pi = reinterpret_cast<PyUNO*>(o);
768 Reference<XMaterialHolder> my_mh (o_pi->members->xInvocation, css::uno::UNO_QUERY_THROW);
769 a = my_mh->getMaterial();
771 else if( PyObject_IsInstance( o, getCharClass( runtime ).get() ) )
773 a <<= PyChar2Unicode( o );
775 else if( PyObject_IsInstance( o, getAnyClass( runtime ).get() ) )
777 if( ACCEPT_UNO_ANY != mode )
779 throw RuntimeException(
780 "uno.Any instance not accepted during method call, "
781 "use uno.invoke instead" );
784 a = pyObject2Any( PyRef( PyObject_GetAttrString( o , "value" ), SAL_NO_ACQUIRE) );
785 Type t;
786 pyObject2Any( PyRef( PyObject_GetAttrString( o, "type" ), SAL_NO_ACQUIRE ) ) >>= t;
790 a = getImpl()->cargo->xTypeConverter->convertTo( a, t );
792 catch( const css::uno::Exception & e )
794 css::uno::Any anyEx = cppu::getCaughtException();
795 throw WrappedTargetRuntimeException(
796 e.Message, e.Context, anyEx);
800 else
802 Reference< XInterface > mappedObject;
803 Reference< XInvocation > adapterObject;
805 // instance already mapped out to the world ?
806 PyRef2Adapter::iterator ii = impl->cargo->mappedObjects.find( PyRef( o ) );
807 if( ii != impl->cargo->mappedObjects.end() )
809 adapterObject = ii->second;
812 if( adapterObject.is() )
814 // object got already bridged !
815 auto pAdapter = comphelper::getFromUnoTunnel<Adapter>(adapterObject);
817 mappedObject = impl->cargo->xAdapterFactory->createAdapter(
818 adapterObject, pAdapter->getWrappedTypes() );
820 else
822 try {
823 Sequence<Type> interfaces = invokeGetTypes(*this, o);
824 if (interfaces.getLength())
826 rtl::Reference<Adapter> pAdapter = new Adapter( o, interfaces );
827 mappedObject =
828 getImpl()->cargo->xAdapterFactory->createAdapter(
829 pAdapter, interfaces );
831 // keep a list of exported objects to ensure object identity !
832 impl->cargo->mappedObjects[ PyRef(o) ] =
833 css::uno::WeakReference< XInvocation > ( pAdapter );
835 } catch (InvocationTargetException const& e) {
836 OUString const msg(lcl_ExceptionMessage(o, &e.Message));
837 throw WrappedTargetRuntimeException( // re-wrap that
838 msg, e.Context, e.TargetException);
841 if( mappedObject.is() )
843 a <<= mappedObject;
845 else
847 OUString const msg(lcl_ExceptionMessage(o, nullptr));
848 throw RuntimeException(msg);
852 return a;
855 Any Runtime::extractUnoException( const PyRef & excType, const PyRef &excValue, const PyRef &excTraceback) const
857 OUString str;
858 Any ret;
859 if( excTraceback.is() )
861 Exception e;
862 PyRef unoModule;
863 if ( impl )
867 unoModule = impl->cargo->getUnoModule();
869 catch (const Exception &ei)
871 e=ei;
874 if( unoModule.is() )
876 PyRef extractTraceback(
877 PyDict_GetItemString(unoModule.get(),"_uno_extract_printable_stacktrace" ) );
879 if( PyCallable_Check(extractTraceback.get()) )
881 PyRef args( PyTuple_New( 1), SAL_NO_ACQUIRE, NOT_NULL );
882 PyTuple_SetItem( args.get(), 0, excTraceback.getAcquired() );
883 PyRef pyStr( PyObject_CallObject( extractTraceback.get(),args.get() ), SAL_NO_ACQUIRE);
884 str = OUString::fromUtf8(PyUnicode_AsUTF8(pyStr.get()));
886 else
888 str = "Couldn't find uno._uno_extract_printable_stacktrace";
891 else
893 str = "Could not load uno.py, no stacktrace available";
894 if ( !e.Message.isEmpty() )
896 str += " (Error loading uno.py: " + e.Message + ")";
901 else
903 // it may occur, that no traceback is given (e.g. only native code below)
904 str = "no traceback available";
907 if( isInstanceOfStructOrException( excValue.get() ) )
909 ret = pyObject2Any( excValue );
911 else
913 OUStringBuffer buf;
914 PyRef typeName( PyObject_Str( excType.get() ), SAL_NO_ACQUIRE );
915 if( typeName.is() )
917 buf.appendAscii( PyUnicode_AsUTF8( typeName.get() ) );
919 else
921 buf.append( "no typename available" );
923 buf.append( ": " );
924 PyRef valueRep( PyObject_Str( excValue.get() ), SAL_NO_ACQUIRE );
925 if( valueRep.is() )
927 buf.appendAscii( PyUnicode_AsUTF8( valueRep.get()));
929 else
931 buf.append( "Couldn't convert exception value to a string" );
933 buf.append( ", traceback follows\n" );
934 if( !str.isEmpty() )
936 buf.append( str );
937 buf.append( "\n" );
939 else
941 buf.append( ", no traceback available\n" );
943 RuntimeException e;
944 e.Message = buf.makeStringAndClear();
945 #if OSL_DEBUG_LEVEL > 0
946 fprintf( stderr, "Python exception: %s\n",
947 OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr() );
948 #endif
949 ret <<= e;
951 return ret;
955 PyThreadAttach::PyThreadAttach( PyInterpreterState *interp)
956 : m_isNewState(false)
958 // note: *may* be called recursively, with PyThreadDetach between - in
959 // that case, don't create *new* PyThreadState but reuse!
960 tstate = PyGILState_GetThisThreadState(); // from TLS, possibly detached
961 if (!tstate)
963 m_isNewState = true;
964 tstate = PyThreadState_New( interp );
966 if( !tstate )
967 throw RuntimeException( "Couldn't create a pythreadstate" );
968 PyEval_AcquireThread( tstate);
971 PyThreadAttach::~PyThreadAttach()
973 if (m_isNewState)
974 { // Clear needs GIL!
975 PyThreadState_Clear( tstate );
976 // note: PyThreadState_Delete(tstate) cannot be called, it will assert
977 // because it requires a PyThreadState to be set, but not the tstate!
978 PyThreadState_DeleteCurrent();
980 else
982 PyEval_ReleaseThread( tstate );
986 PyThreadDetach::PyThreadDetach()
988 tstate = PyThreadState_Get();
989 PyEval_ReleaseThread( tstate );
990 // tstate must not be deleted here! lots of pointers to it on the stack
993 /** Acquires the global interpreter lock again
996 PyThreadDetach::~PyThreadDetach()
998 PyEval_AcquireThread( tstate );
1002 PyRef const & RuntimeCargo::getUnoModule()
1004 if( ! dictUnoModule.is() )
1006 dictUnoModule = importUnoModule();
1008 return dictUnoModule;
1012 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */