Version 7.1.7.1, tag libreoffice-7.1.7.1
[LibreOffice.git] / pyuno / source / module / pyuno_runtime.cxx
blob91005f1e13aa0e570df2b618ba1cf4934acd0076
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>
32 #include <typelib/typedescription.hxx>
34 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
35 #include <com/sun/star/beans/XMaterialHolder.hpp>
36 #include <com/sun/star/beans/theIntrospection.hpp>
37 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
38 #include <com/sun/star/script/Converter.hpp>
39 #include <com/sun/star/script/InvocationAdapterFactory.hpp>
40 #include <com/sun/star/script/XInvocation2.hpp>
41 #include <com/sun/star/reflection/theCoreReflection.hpp>
42 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
43 #include <comphelper/sequence.hxx>
44 #include <comphelper/servicehelper.hxx>
45 #include <cppuhelper/exc_hlp.hxx>
47 #include <vector>
49 using com::sun::star::uno::Reference;
50 using com::sun::star::uno::XInterface;
51 using com::sun::star::uno::Any;
52 using com::sun::star::uno::TypeDescription;
53 using com::sun::star::uno::Sequence;
54 using com::sun::star::uno::Type;
55 using com::sun::star::uno::UNO_QUERY;
56 using com::sun::star::uno::Exception;
57 using com::sun::star::uno::RuntimeException;
58 using com::sun::star::uno::XComponentContext;
59 using com::sun::star::lang::WrappedTargetRuntimeException;
60 using com::sun::star::lang::XSingleServiceFactory;
61 using com::sun::star::lang::XUnoTunnel;
62 using com::sun::star::reflection::theCoreReflection;
63 using com::sun::star::reflection::InvocationTargetException;
64 using com::sun::star::script::Converter;
65 using com::sun::star::script::XTypeConverter;
66 using com::sun::star::script::XInvocation;
67 using com::sun::star::beans::XMaterialHolder;
68 using com::sun::star::beans::theIntrospection;
70 namespace pyuno
73 static PyTypeObject RuntimeImpl_Type =
75 PyVarObject_HEAD_INIT (&PyType_Type, 0)
76 "pyuno_runtime",
77 sizeof (RuntimeImpl),
79 RuntimeImpl::del,
80 #if PY_VERSION_HEX >= 0x03080000
81 0, // Py_ssize_t tp_vectorcall_offset
82 #else
83 nullptr, // printfunc tp_print
84 #endif
85 nullptr,
86 nullptr,
87 nullptr,
88 nullptr,
89 nullptr,
90 nullptr,
91 nullptr,
92 nullptr,
93 nullptr,
94 nullptr,
95 nullptr,
96 nullptr,
97 nullptr,
99 nullptr,
100 nullptr,
101 nullptr,
102 nullptr,
104 nullptr,
105 nullptr,
106 nullptr,
107 nullptr,
108 nullptr,
109 nullptr,
110 nullptr,
111 nullptr,
112 nullptr,
114 nullptr,
115 nullptr,
116 nullptr,
117 nullptr,
118 nullptr,
119 nullptr,
120 nullptr,
121 nullptr,
122 nullptr,
123 nullptr,
124 nullptr
126 #if PY_VERSION_HEX >= 0x03040000
127 , nullptr
128 #if PY_VERSION_HEX >= 0x03080000
129 , nullptr // vectorcallfunc tp_vectorcall
130 #if PY_VERSION_HEX < 0x03090000
131 #if defined __clang__
132 #pragma clang diagnostic push
133 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
134 #endif
135 , nullptr // tp_print
136 #if defined __clang__
137 #pragma clang diagnostic pop
138 #endif
139 #endif
140 #endif
141 #endif
144 /*----------------------------------------------------------------------
145 Runtime implementation
146 -----------------------------------------------------------------------*/
147 /// @throws css::uno::RuntimeException
148 static void getRuntimeImpl( PyRef & globalDict, PyRef &runtimeImpl )
150 PyThreadState * state = PyThreadState_Get();
151 if( ! state )
153 throw RuntimeException( "python global interpreter must be held (thread must be attached)" );
156 PyObject* pModule = PyImport_AddModule("__main__");
158 if (!pModule)
160 throw RuntimeException("can't import __main__ module");
163 globalDict = PyRef( PyModule_GetDict(pModule));
165 if( ! globalDict.is() ) // FATAL !
167 throw RuntimeException("can't find __main__ module");
169 runtimeImpl = PyDict_GetItemString( globalDict.get() , "pyuno_runtime" );
172 /// @throws RuntimeException
173 static PyRef importUnoModule( )
175 // import the uno module
176 PyRef module( PyImport_ImportModule( "uno" ), SAL_NO_ACQUIRE, NOT_NULL );
177 if( PyErr_Occurred() )
179 PyRef excType, excValue, excTraceback;
180 PyErr_Fetch( reinterpret_cast<PyObject **>(&excType), reinterpret_cast<PyObject**>(&excValue), reinterpret_cast<PyObject**>(&excTraceback));
181 // As of Python 2.7 this gives a rather non-useful "<traceback object at 0xADDRESS>",
182 // but it is the best we can do in the absence of uno._uno_extract_printable_stacktrace
183 // Who knows, a future Python might print something better.
184 PyRef str( PyObject_Str( excTraceback.get() ), SAL_NO_ACQUIRE );
186 OUStringBuffer buf;
187 buf.append( "python object raised an unknown exception (" );
188 PyRef valueRep( PyObject_Repr( excValue.get() ), SAL_NO_ACQUIRE );
189 buf.appendAscii( PyUnicode_AsUTF8( valueRep.get())).append( ", traceback follows\n" );
190 buf.appendAscii( PyUnicode_AsUTF8( str.get() ) );
191 buf.append( ")" );
192 throw RuntimeException( buf.makeStringAndClear() );
194 PyRef dict( PyModule_GetDict( module.get() ) );
195 return dict;
198 static void readLoggingConfig( sal_Int32 *pLevel, FILE **ppFile )
200 *pLevel = LogLevel::NONE;
201 *ppFile = nullptr;
202 OUString fileName;
203 osl_getModuleURLFromFunctionAddress(
204 reinterpret_cast< oslGenericFunction >(readLoggingConfig),
205 &fileName.pData );
206 fileName = fileName.copy( fileName.lastIndexOf( '/' )+1 );
207 #ifdef MACOSX
208 fileName += "../" LIBO_ETC_FOLDER "/";
209 #endif
210 fileName += SAL_CONFIGFILE("pyuno" );
211 rtl::Bootstrap bootstrapHandle( fileName );
213 OUString str;
214 if( bootstrapHandle.getFrom( "PYUNO_LOGLEVEL", str ) )
216 if ( str == "NONE" )
217 *pLevel = LogLevel::NONE;
218 else if ( str == "CALL" )
219 *pLevel = LogLevel::CALL;
220 else if ( str == "ARGS" )
221 *pLevel = LogLevel::ARGS;
222 else
224 fprintf( stderr, "unknown loglevel %s\n",
225 OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
228 if( *pLevel <= LogLevel::NONE )
229 return;
231 *ppFile = stdout;
232 if( !bootstrapHandle.getFrom( "PYUNO_LOGTARGET", str ) )
233 return;
235 if ( str == "stdout" )
236 *ppFile = stdout;
237 else if ( str == "stderr" )
238 *ppFile = stderr;
239 else
241 oslProcessInfo data;
242 data.Size = sizeof( data );
243 osl_getProcessInfo(
244 nullptr , osl_Process_IDENTIFIER , &data );
245 osl_getSystemPathFromFileURL( str.pData, &str.pData);
246 OString o = OUStringToOString( str, osl_getThreadTextEncoding() );
247 o += ".";
248 o += OString::number( data.Ident );
250 *ppFile = fopen( o.getStr() , "w" );
251 if ( *ppFile )
253 // do not buffer (useful if e.g. analyzing a crash)
254 setvbuf( *ppFile, nullptr, _IONBF, 0 );
256 else
258 fprintf( stderr, "couldn't create file %s\n",
259 OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
265 /*-------------------------------------------------------------------
266 RuntimeImpl implementations
267 *-------------------------------------------------------------------*/
268 PyRef stRuntimeImpl::create( const Reference< XComponentContext > &ctx )
270 RuntimeImpl *me = PyObject_New (RuntimeImpl, &RuntimeImpl_Type);
271 if( ! me )
272 throw RuntimeException( "cannot instantiate pyuno::RuntimeImpl" );
273 me->cargo = nullptr;
274 // must use a different struct here, as the PyObject_New
275 // makes C++ unusable
276 RuntimeCargo *c = new RuntimeCargo;
277 readLoggingConfig( &(c->logLevel) , &(c->logFile) );
278 log( c, LogLevel::CALL, "Instantiating pyuno bridge" );
280 c->valid = true;
281 c->xContext = ctx;
282 c->xInvocation = Reference< XSingleServiceFactory > (
283 ctx->getServiceManager()->createInstanceWithContext(
284 "com.sun.star.script.Invocation",
285 ctx ),
286 css::uno::UNO_QUERY_THROW );
288 c->xTypeConverter = Converter::create(ctx);
289 if( ! c->xTypeConverter.is() )
290 throw RuntimeException( "pyuno: couldn't instantiate typeconverter service" );
292 c->xCoreReflection = theCoreReflection::get(ctx);
294 c->xAdapterFactory = css::script::InvocationAdapterFactory::create(ctx);
296 c->xIntrospection = theIntrospection::get(ctx);
298 Any a = ctx->getValueByName("/singletons/com.sun.star.reflection.theTypeDescriptionManager");
299 a >>= c->xTdMgr;
300 if( ! c->xTdMgr.is() )
301 throw RuntimeException( "pyuno: couldn't retrieve typedescriptionmanager" );
303 me->cargo =c;
304 return PyRef( reinterpret_cast< PyObject * > ( me ), SAL_NO_ACQUIRE );
307 void stRuntimeImpl::del(PyObject* self)
309 RuntimeImpl *me = reinterpret_cast< RuntimeImpl * > ( self );
310 if( me->cargo->logFile )
311 fclose( me->cargo->logFile );
312 delete me->cargo;
313 PyObject_Del (self);
317 void Runtime::initialize( const Reference< XComponentContext > & ctx )
319 PyRef globalDict, runtime;
320 getRuntimeImpl( globalDict , runtime );
321 RuntimeImpl *impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
323 if( runtime.is() && impl->cargo->valid )
325 throw RuntimeException("pyuno runtime has already been initialized before" );
327 PyRef keep( RuntimeImpl::create( ctx ) );
328 PyDict_SetItemString( globalDict.get(), "pyuno_runtime" , keep.get() );
329 Py_XINCREF( keep.get() );
333 bool Runtime::isInitialized()
335 PyRef globalDict, runtime;
336 getRuntimeImpl( globalDict , runtime );
337 RuntimeImpl *impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
338 return runtime.is() && impl->cargo->valid;
341 Runtime::Runtime()
342 : impl( nullptr )
344 PyRef globalDict, runtime;
345 getRuntimeImpl( globalDict , runtime );
346 if( ! runtime.is() )
348 throw RuntimeException(
349 "pyuno runtime is not initialized, "
350 "(the pyuno.bootstrap needs to be called before using any uno classes)" );
352 impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
353 Py_XINCREF( runtime.get() );
356 Runtime::Runtime( const Runtime & r )
358 impl = r.impl;
359 Py_XINCREF( reinterpret_cast< PyObject * >(impl) );
362 Runtime::~Runtime()
364 Py_XDECREF( reinterpret_cast< PyObject * >(impl) );
367 Runtime & Runtime::operator = ( const Runtime & r )
369 PyRef temp( reinterpret_cast< PyObject * >(r.impl) );
370 Py_XINCREF( temp.get() );
371 Py_XDECREF( reinterpret_cast< PyObject * >(impl) );
372 impl = r.impl;
373 return *this;
376 PyRef Runtime::any2PyObject (const Any &a ) const
378 if( ! impl->cargo->valid )
380 throw RuntimeException("pyuno runtime must be initialized before calling any2PyObject" );
383 switch (a.getValueTypeClass ())
385 case css::uno::TypeClass_VOID:
387 Py_INCREF (Py_None);
388 return PyRef(Py_None);
390 case css::uno::TypeClass_CHAR:
392 sal_Unicode c = *o3tl::forceAccess<sal_Unicode>(a);
393 return PyRef( PyUNO_char_new( c , *this ), SAL_NO_ACQUIRE );
395 case css::uno::TypeClass_BOOLEAN:
397 bool b;
398 if ((a >>= b) && b)
399 return Py_True;
400 else
401 return Py_False;
403 case css::uno::TypeClass_BYTE:
404 case css::uno::TypeClass_SHORT:
405 case css::uno::TypeClass_UNSIGNED_SHORT:
406 case css::uno::TypeClass_LONG:
408 sal_Int32 l = 0;
409 a >>= l;
410 return PyRef( PyLong_FromLong (l), SAL_NO_ACQUIRE );
412 case css::uno::TypeClass_UNSIGNED_LONG:
414 sal_uInt32 l = 0;
415 a >>= l;
416 return PyRef( PyLong_FromUnsignedLong (l), SAL_NO_ACQUIRE );
418 case css::uno::TypeClass_HYPER:
420 sal_Int64 l = 0;
421 a >>= l;
422 return PyRef( PyLong_FromLongLong (l), SAL_NO_ACQUIRE);
424 case css::uno::TypeClass_UNSIGNED_HYPER:
426 sal_uInt64 l = 0;
427 a >>= l;
428 return PyRef( PyLong_FromUnsignedLongLong (l), SAL_NO_ACQUIRE);
430 case css::uno::TypeClass_FLOAT:
432 float f = 0.0;
433 a >>= f;
434 return PyRef(PyFloat_FromDouble (f), SAL_NO_ACQUIRE);
436 case css::uno::TypeClass_DOUBLE:
438 double d = 0.0;
439 a >>= d;
440 return PyRef( PyFloat_FromDouble (d), SAL_NO_ACQUIRE);
442 case css::uno::TypeClass_STRING:
444 OUString tmp_ostr;
445 a >>= tmp_ostr;
446 return ustring2PyUnicode( tmp_ostr );
448 case css::uno::TypeClass_TYPE:
450 Type t;
451 a >>= t;
452 OString o = OUStringToOString( t.getTypeName(), RTL_TEXTENCODING_ASCII_US );
453 return PyRef(
454 PyUNO_Type_new (
455 o.getStr(), t.getTypeClass(), *this),
456 SAL_NO_ACQUIRE);
458 case css::uno::TypeClass_ANY:
460 //I don't think this can happen.
461 Py_INCREF (Py_None);
462 return Py_None;
464 case css::uno::TypeClass_ENUM:
466 sal_Int32 l = *static_cast<sal_Int32 const *>(a.getValue());
467 TypeDescription desc( a.getValueType() );
468 if( desc.is() )
470 desc.makeComplete();
471 typelib_EnumTypeDescription *pEnumDesc =
472 reinterpret_cast<typelib_EnumTypeDescription *>(desc.get());
473 for( int i = 0 ; i < pEnumDesc->nEnumValues ; i ++ )
475 if( pEnumDesc->pEnumValues[i] == l )
477 OString v = OUStringToOString( pEnumDesc->ppEnumNames[i], RTL_TEXTENCODING_ASCII_US);
478 OString e = OUStringToOString( pEnumDesc->aBase.pTypeName, RTL_TEXTENCODING_ASCII_US);
479 return PyRef( PyUNO_Enum_new(e.getStr(),v.getStr(), *this ), SAL_NO_ACQUIRE );
483 throw RuntimeException( "Any carries enum " + a.getValueType().getTypeName() +
484 " with invalid value " + OUString::number(l) );
486 case css::uno::TypeClass_EXCEPTION:
487 case css::uno::TypeClass_STRUCT:
489 PyRef excClass = getClass( a.getValueType().getTypeName(), *this );
490 PyRef value = PyUNOStruct_new( a, getImpl()->cargo->xInvocation );
491 PyRef argsTuple( PyTuple_New( 1 ) , SAL_NO_ACQUIRE, NOT_NULL );
492 PyTuple_SetItem( argsTuple.get() , 0 , value.getAcquired() );
493 PyRef ret( PyObject_CallObject( excClass.get() , argsTuple.get() ), SAL_NO_ACQUIRE );
494 if( ! ret.is() )
496 throw RuntimeException( "Couldn't instantiate python representation of structured UNO type " +
497 a.getValueType().getTypeName() );
500 if( auto e = o3tl::tryAccess<css::uno::Exception>(a) )
502 // add the message in a standard python way !
503 PyRef args( PyTuple_New( 1 ), SAL_NO_ACQUIRE, NOT_NULL );
505 PyRef pymsg = ustring2PyString( e->Message );
506 PyTuple_SetItem( args.get(), 0 , pymsg.getAcquired() );
507 // the exception base functions want to have an "args" tuple,
508 // which contains the message
509 PyObject_SetAttrString( ret.get(), "args", args.get() );
511 return ret;
513 case css::uno::TypeClass_SEQUENCE:
515 Sequence<Any> s;
517 Sequence< sal_Int8 > byteSequence;
518 if( a >>= byteSequence )
520 // byte sequence is treated in a special way because of performance reasons
521 // @since 0.9.2
522 return PyRef( PyUNO_ByteSequence_new( byteSequence, *this ), SAL_NO_ACQUIRE );
524 else
526 Reference< XTypeConverter > tc = getImpl()->cargo->xTypeConverter;
527 tc->convertTo (a, cppu::UnoType<decltype(s)>::get()) >>= s;
528 PyRef tuple( PyTuple_New (s.getLength()), SAL_NO_ACQUIRE, NOT_NULL);
529 int i=0;
532 for ( i = 0; i < s.getLength (); i++)
534 PyRef element = any2PyObject (tc->convertTo (s[i], s[i].getValueType() ));
535 OSL_ASSERT( element.is() );
536 PyTuple_SetItem( tuple.get(), i, element.getAcquired() );
539 catch( css::uno::Exception & )
541 for( ; i < s.getLength() ; i ++ )
543 Py_INCREF( Py_None );
544 PyTuple_SetItem( tuple.get(), i, Py_None );
546 throw;
548 return tuple;
551 case css::uno::TypeClass_INTERFACE:
553 Reference<XInterface> tmp_interface;
554 a >>= tmp_interface;
555 if (!tmp_interface.is ())
556 return Py_None;
558 return PyUNO_new( a, getImpl()->cargo->xInvocation );
560 default:
562 throw RuntimeException( "Unknown UNO type class " + OUString::number(static_cast<int>(a.getValueTypeClass())) );
567 static Sequence< Type > invokeGetTypes( const Runtime & r , PyObject * o )
569 Sequence< Type > ret;
571 PyRef method( PyObject_GetAttrString( o , "getTypes" ), SAL_NO_ACQUIRE );
572 raiseInvocationTargetExceptionWhenNeeded( r );
573 if( method.is() && PyCallable_Check( method.get() ) )
575 PyRef types( PyObject_CallObject( method.get(), nullptr ) , SAL_NO_ACQUIRE );
576 raiseInvocationTargetExceptionWhenNeeded( r );
577 if( types.is() && PyTuple_Check( types.get() ) )
579 int size = PyTuple_Size( types.get() );
581 // add the XUnoTunnel interface for uno object identity concept (hack)
582 ret.realloc( size + 1 );
583 for( int i = 0 ; i < size ; i ++ )
585 Any a = r.pyObject2Any(PyTuple_GetItem(types.get(),i));
586 a >>= ret[i];
588 ret[size] = cppu::UnoType<css::lang::XUnoTunnel>::get();
591 return ret;
594 static OUString
595 lcl_ExceptionMessage(PyObject *const o, OUString const*const pWrapped)
597 OUStringBuffer buf;
598 buf.append("Couldn't convert ");
599 PyRef reprString( PyObject_Str(o), SAL_NO_ACQUIRE );
600 buf.appendAscii( PyUnicode_AsUTF8(reprString.get()) );
601 buf.append(" to a UNO type");
602 if (pWrapped)
604 buf.append("; caught exception: ");
605 buf.append(*pWrapped);
607 return buf.makeStringAndClear();
610 // For Python 2.7 - see https://bugs.python.org/issue24161
611 // Fills aSeq and returns true if pObj is a valid iterator
612 bool Runtime::pyIterUnpack( PyObject *const pObj, Any &a ) const
614 if( !PyIter_Check( pObj ))
615 return false;
617 PyObject *pItem = PyIter_Next( pObj );
618 if( !pItem )
620 if( PyErr_Occurred() )
622 PyErr_Clear();
623 return false;
625 return true;
628 ::std::vector<Any> items;
631 PyRef rItem( pItem, SAL_NO_ACQUIRE );
632 items.push_back( pyObject2Any( rItem.get() ) );
633 pItem = PyIter_Next( pObj );
635 while( pItem );
636 a <<= comphelper::containerToSequence(items);
637 return true;
640 Any Runtime::pyObject2Any ( const PyRef & source, enum ConversionMode mode ) const
642 if( ! impl->cargo->valid )
644 throw RuntimeException("pyuno runtime must be initialized before calling any2PyObject" );
647 Any a;
648 PyObject *o = source.get();
649 if( Py_None == o )
653 else if (PyLong_Check (o))
655 // Convert the Python 3 booleans that are actually of type PyLong.
656 if(o == Py_True)
658 a <<= true;
660 else if(o == Py_False)
662 a <<= false;
664 else
666 sal_Int64 l = static_cast<sal_Int64>(PyLong_AsLong (o));
667 if( l < 128 && l >= -128 )
669 sal_Int8 b = static_cast<sal_Int8>(l);
670 a <<= b;
672 else if( l <= 0x7fff && l >= -0x8000 )
674 sal_Int16 s = static_cast<sal_Int16>(l);
675 a <<= s;
677 else if( l <= SAL_CONST_INT64(0x7fffffff) &&
678 l >= -SAL_CONST_INT64(0x80000000) )
680 sal_Int32 l32 = static_cast<sal_Int32>(l);
681 a <<= l32;
683 else
685 a <<= l;
689 else if (PyFloat_Check (o))
691 double d = PyFloat_AsDouble (o);
692 a <<= d;
694 else if (PyBytes_Check(o) || PyUnicode_Check(o))
696 a <<= pyString2ustring(o);
698 else if (PyTuple_Check (o))
700 Sequence<Any> s (PyTuple_Size (o));
701 for (Py_ssize_t i = 0; i < PyTuple_Size (o); i++)
703 s[i] = pyObject2Any (PyTuple_GetItem (o, i), mode );
705 a <<= s;
707 else if (PyList_Check (o))
709 Py_ssize_t l = PyList_Size (o);
710 Sequence<Any> s (l);
711 for (Py_ssize_t i = 0; i < l; i++)
713 s[i] = pyObject2Any (PyList_GetItem (o, i), mode );
715 a <<= s;
717 else if (!pyIterUnpack (o, a))
719 Runtime runtime;
720 // should be removed, in case ByteSequence gets derived from String
721 if( PyObject_IsInstance( o, getByteSequenceClass( runtime ).get() ) )
723 PyRef str(PyObject_GetAttrString( o , "value" ),SAL_NO_ACQUIRE);
724 Sequence< sal_Int8 > seq;
725 if( PyBytes_Check( str.get() ) )
727 seq = Sequence<sal_Int8 > (
728 reinterpret_cast<sal_Int8*>(PyBytes_AsString(str.get())), PyBytes_Size(str.get()));
730 a <<= seq;
732 else
733 if( PyObject_IsInstance( o, getTypeClass( runtime ).get() ) )
735 Type t = PyType2Type( o );
736 a <<= t;
738 else if( PyObject_IsInstance( o, getEnumClass( runtime ).get() ) )
740 a = PyEnum2Enum( o );
742 else if( isInstanceOfStructOrException( o ) )
744 PyRef struc(PyObject_GetAttrString( o , "value" ),SAL_NO_ACQUIRE);
745 PyUNO * obj = reinterpret_cast<PyUNO*>(struc.get());
746 Reference< XMaterialHolder > holder( obj->members->xInvocation, UNO_QUERY );
747 if( !holder.is( ) )
749 throw RuntimeException(
750 "struct or exception wrapper does not support XMaterialHolder" );
753 a = holder->getMaterial();
756 else if( PyObject_IsInstance( o, getPyUnoClass().get() ) )
758 PyUNO* o_pi = reinterpret_cast<PyUNO*>(o);
759 a = o_pi->members->wrappedObject;
761 else if( PyObject_IsInstance( o, getPyUnoStructClass().get() ) )
763 PyUNO* o_pi = reinterpret_cast<PyUNO*>(o);
764 Reference<XMaterialHolder> my_mh (o_pi->members->xInvocation, css::uno::UNO_QUERY_THROW);
765 a = my_mh->getMaterial();
767 else if( PyObject_IsInstance( o, getCharClass( runtime ).get() ) )
769 a <<= PyChar2Unicode( o );
771 else if( PyObject_IsInstance( o, getAnyClass( runtime ).get() ) )
773 if( ACCEPT_UNO_ANY != mode )
775 throw RuntimeException(
776 "uno.Any instance not accepted during method call, "
777 "use uno.invoke instead" );
780 a = pyObject2Any( PyRef( PyObject_GetAttrString( o , "value" ), SAL_NO_ACQUIRE) );
781 Type t;
782 pyObject2Any( PyRef( PyObject_GetAttrString( o, "type" ), SAL_NO_ACQUIRE ) ) >>= t;
786 a = getImpl()->cargo->xTypeConverter->convertTo( a, t );
788 catch( const css::uno::Exception & e )
790 css::uno::Any anyEx = cppu::getCaughtException();
791 throw WrappedTargetRuntimeException(
792 e.Message, e.Context, anyEx);
796 else
798 Reference< XInterface > mappedObject;
799 Reference< XInvocation > adapterObject;
801 // instance already mapped out to the world ?
802 PyRef2Adapter::iterator ii = impl->cargo->mappedObjects.find( PyRef( o ) );
803 if( ii != impl->cargo->mappedObjects.end() )
805 adapterObject = ii->second;
808 if( adapterObject.is() )
810 // object got already bridged !
811 auto pAdapter = comphelper::getUnoTunnelImplementation<Adapter>(adapterObject);
813 mappedObject = impl->cargo->xAdapterFactory->createAdapter(
814 adapterObject, pAdapter->getWrappedTypes() );
816 else
818 try {
819 Sequence<Type> interfaces = invokeGetTypes(*this, o);
820 if (interfaces.getLength())
822 Adapter *pAdapter = new Adapter( o, interfaces );
823 mappedObject =
824 getImpl()->cargo->xAdapterFactory->createAdapter(
825 pAdapter, interfaces );
827 // keep a list of exported objects to ensure object identity !
828 impl->cargo->mappedObjects[ PyRef(o) ] =
829 css::uno::WeakReference< XInvocation > ( pAdapter );
831 } catch (InvocationTargetException const& e) {
832 OUString const msg(lcl_ExceptionMessage(o, &e.Message));
833 throw WrappedTargetRuntimeException( // re-wrap that
834 msg, e.Context, e.TargetException);
837 if( mappedObject.is() )
839 a <<= mappedObject;
841 else
843 OUString const msg(lcl_ExceptionMessage(o, nullptr));
844 throw RuntimeException(msg);
848 return a;
851 Any Runtime::extractUnoException( const PyRef & excType, const PyRef &excValue, const PyRef &excTraceback) const
853 OUString str;
854 Any ret;
855 if( excTraceback.is() )
857 Exception e;
858 PyRef unoModule;
859 if ( impl )
863 unoModule = impl->cargo->getUnoModule();
865 catch (const Exception &ei)
867 e=ei;
870 if( unoModule.is() )
872 PyRef extractTraceback(
873 PyDict_GetItemString(unoModule.get(),"_uno_extract_printable_stacktrace" ) );
875 if( PyCallable_Check(extractTraceback.get()) )
877 PyRef args( PyTuple_New( 1), SAL_NO_ACQUIRE, NOT_NULL );
878 PyTuple_SetItem( args.get(), 0, excTraceback.getAcquired() );
879 PyRef pyStr( PyObject_CallObject( extractTraceback.get(),args.get() ), SAL_NO_ACQUIRE);
880 str = OUString::createFromAscii( PyUnicode_AsUTF8(pyStr.get()) );
882 else
884 str = "Couldn't find uno._uno_extract_printable_stacktrace";
887 else
889 str = "Could not load uno.py, no stacktrace available";
890 if ( !e.Message.isEmpty() )
892 str += " (Error loading uno.py: " + e.Message + ")";
897 else
899 // it may occur, that no traceback is given (e.g. only native code below)
900 str = "no traceback available";
903 if( isInstanceOfStructOrException( excValue.get() ) )
905 ret = pyObject2Any( excValue );
907 else
909 OUStringBuffer buf;
910 PyRef typeName( PyObject_Str( excType.get() ), SAL_NO_ACQUIRE );
911 if( typeName.is() )
913 buf.appendAscii( PyUnicode_AsUTF8( typeName.get() ) );
915 else
917 buf.append( "no typename available" );
919 buf.append( ": " );
920 PyRef valueRep( PyObject_Str( excValue.get() ), SAL_NO_ACQUIRE );
921 if( valueRep.is() )
923 buf.appendAscii( PyUnicode_AsUTF8( valueRep.get()));
925 else
927 buf.append( "Couldn't convert exception value to a string" );
929 buf.append( ", traceback follows\n" );
930 if( !str.isEmpty() )
932 buf.append( str );
933 buf.append( "\n" );
935 else
937 buf.append( ", no traceback available\n" );
939 RuntimeException e;
940 e.Message = buf.makeStringAndClear();
941 #if OSL_DEBUG_LEVEL > 0
942 fprintf( stderr, "Python exception: %s\n",
943 OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr() );
944 #endif
945 ret <<= e;
947 return ret;
951 PyThreadAttach::PyThreadAttach( PyInterpreterState *interp)
952 : m_isNewState(false)
954 // note: *may* be called recursively, with PyThreadDetach between - in
955 // that case, don't create *new* PyThreadState but reuse!
956 tstate = PyGILState_GetThisThreadState(); // from TLS, possibly detached
957 if (!tstate)
959 m_isNewState = true;
960 tstate = PyThreadState_New( interp );
962 if( !tstate )
963 throw RuntimeException( "Couldn't create a pythreadstate" );
964 PyEval_AcquireThread( tstate);
967 PyThreadAttach::~PyThreadAttach()
969 if (m_isNewState)
970 { // Clear needs GIL!
971 PyThreadState_Clear( tstate );
972 // note: PyThreadState_Delete(tstate) cannot be called, it will assert
973 // because it requires a PyThreadState to be set, but not the tstate!
974 PyThreadState_DeleteCurrent();
976 else
978 PyEval_ReleaseThread( tstate );
982 PyThreadDetach::PyThreadDetach()
984 tstate = PyThreadState_Get();
985 PyEval_ReleaseThread( tstate );
986 // tstate must not be deleted here! lots of pointers to it on the stack
989 /** Acquires the global interpreter lock again
992 PyThreadDetach::~PyThreadDetach()
994 PyEval_AcquireThread( tstate );
998 PyRef const & RuntimeCargo::getUnoModule()
1000 if( ! dictUnoModule.is() )
1002 dictUnoModule = importUnoModule();
1004 return dictUnoModule;
1008 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */