1 /* -*- Mode: C++; eval:(c-set-style "bsd"); tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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
;
73 static PyTypeObject RuntimeImpl_Type
=
75 PyVarObject_HEAD_INIT (&PyType_Type
, 0)
80 #if PY_VERSION_HEX >= 0x03080000
81 0, // Py_ssize_t tp_vectorcall_offset
83 nullptr, // printfunc tp_print
126 #if PY_VERSION_HEX >= 0x03040000
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"
135 , nullptr // tp_print
136 #if defined __clang__
137 #pragma clang diagnostic pop
144 /*----------------------------------------------------------------------
145 Runtime implementation
146 -----------------------------------------------------------------------*/
147 /// @throws css::uno::RuntimeException
148 static void getRuntimeImpl( PyRef
& globalDict
, PyRef
&runtimeImpl
)
150 PyThreadState
* state
= PyThreadState_Get();
153 throw RuntimeException( "python global interpreter must be held (thread must be attached)" );
156 PyObject
* pModule
= PyImport_AddModule("__main__");
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
);
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() ) );
192 throw RuntimeException( buf
.makeStringAndClear() );
194 PyRef
dict( PyModule_GetDict( module
.get() ) );
198 static void readLoggingConfig( sal_Int32
*pLevel
, FILE **ppFile
)
200 *pLevel
= LogLevel::NONE
;
203 osl_getModuleURLFromFunctionAddress(
204 reinterpret_cast< oslGenericFunction
>(readLoggingConfig
),
206 fileName
= fileName
.copy( fileName
.lastIndexOf( '/' )+1 );
208 fileName
+= "../" LIBO_ETC_FOLDER
"/";
210 fileName
+= SAL_CONFIGFILE("pyuno" );
211 rtl::Bootstrap
bootstrapHandle( fileName
);
214 if( bootstrapHandle
.getFrom( "PYUNO_LOGLEVEL", str
) )
217 *pLevel
= LogLevel::NONE
;
218 else if ( str
== "CALL" )
219 *pLevel
= LogLevel::CALL
;
220 else if ( str
== "ARGS" )
221 *pLevel
= LogLevel::ARGS
;
224 fprintf( stderr
, "unknown loglevel %s\n",
225 OUStringToOString( str
, RTL_TEXTENCODING_UTF8
).getStr() );
228 if( *pLevel
<= LogLevel::NONE
)
232 if( !bootstrapHandle
.getFrom( "PYUNO_LOGTARGET", str
) )
235 if ( str
== "stdout" )
237 else if ( str
== "stderr" )
242 data
.Size
= sizeof( data
);
244 nullptr , osl_Process_IDENTIFIER
, &data
);
245 osl_getSystemPathFromFileURL( str
.pData
, &str
.pData
);
246 OString o
= OUStringToOString( str
, osl_getThreadTextEncoding() );
248 o
+= OString::number( data
.Ident
);
250 *ppFile
= fopen( o
.getStr() , "w" );
253 // do not buffer (useful if e.g. analyzing a crash)
254 setvbuf( *ppFile
, nullptr, _IONBF
, 0 );
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
);
272 throw RuntimeException( "cannot instantiate pyuno::RuntimeImpl" );
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" );
282 c
->xInvocation
= Reference
< XSingleServiceFactory
> (
283 ctx
->getServiceManager()->createInstanceWithContext(
284 "com.sun.star.script.Invocation",
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");
300 if( ! c
->xTdMgr
.is() )
301 throw RuntimeException( "pyuno: couldn't retrieve typedescriptionmanager" );
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
);
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
;
344 PyRef globalDict
, runtime
;
345 getRuntimeImpl( globalDict
, runtime
);
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
)
359 Py_XINCREF( reinterpret_cast< PyObject
* >(impl
) );
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
) );
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
:
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
:
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
:
410 return PyRef( PyLong_FromLong (l
), SAL_NO_ACQUIRE
);
412 case css::uno::TypeClass_UNSIGNED_LONG
:
416 return PyRef( PyLong_FromUnsignedLong (l
), SAL_NO_ACQUIRE
);
418 case css::uno::TypeClass_HYPER
:
422 return PyRef( PyLong_FromLongLong (l
), SAL_NO_ACQUIRE
);
424 case css::uno::TypeClass_UNSIGNED_HYPER
:
428 return PyRef( PyLong_FromUnsignedLongLong (l
), SAL_NO_ACQUIRE
);
430 case css::uno::TypeClass_FLOAT
:
434 return PyRef(PyFloat_FromDouble (f
), SAL_NO_ACQUIRE
);
436 case css::uno::TypeClass_DOUBLE
:
440 return PyRef( PyFloat_FromDouble (d
), SAL_NO_ACQUIRE
);
442 case css::uno::TypeClass_STRING
:
446 return ustring2PyUnicode( tmp_ostr
);
448 case css::uno::TypeClass_TYPE
:
452 OString o
= OUStringToOString( t
.getTypeName(), RTL_TEXTENCODING_ASCII_US
);
455 o
.getStr(), t
.getTypeClass(), *this),
458 case css::uno::TypeClass_ANY
:
460 //I don't think this can happen.
464 case css::uno::TypeClass_ENUM
:
466 sal_Int32 l
= *static_cast<sal_Int32
const *>(a
.getValue());
467 TypeDescription
desc( a
.getValueType() );
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
);
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() );
513 case css::uno::TypeClass_SEQUENCE
:
517 Sequence
< sal_Int8
> byteSequence
;
518 if( a
>>= byteSequence
)
520 // byte sequence is treated in a special way because of performance reasons
522 return PyRef( PyUNO_ByteSequence_new( byteSequence
, *this ), SAL_NO_ACQUIRE
);
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
);
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
);
551 case css::uno::TypeClass_INTERFACE
:
553 Reference
<XInterface
> tmp_interface
;
555 if (!tmp_interface
.is ())
558 return PyUNO_new( a
, getImpl()->cargo
->xInvocation
);
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
));
588 ret
[size
] = cppu::UnoType
<css::lang::XUnoTunnel
>::get();
595 lcl_ExceptionMessage(PyObject
*const o
, OUString
const*const pWrapped
)
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");
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
))
617 PyObject
*pItem
= PyIter_Next( pObj
);
620 if( PyErr_Occurred() )
628 ::std::vector
<Any
> items
;
631 PyRef
rItem( pItem
, SAL_NO_ACQUIRE
);
632 items
.push_back( pyObject2Any( rItem
.get() ) );
633 pItem
= PyIter_Next( pObj
);
636 a
<<= comphelper::containerToSequence(items
);
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" );
648 PyObject
*o
= source
.get();
653 else if (PyLong_Check (o
))
655 // Convert the Python 3 booleans that are actually of type PyLong.
660 else if(o
== Py_False
)
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
);
672 else if( l
<= 0x7fff && l
>= -0x8000 )
674 sal_Int16 s
= static_cast<sal_Int16
>(l
);
677 else if( l
<= SAL_CONST_INT64(0x7fffffff) &&
678 l
>= -SAL_CONST_INT64(0x80000000) )
680 sal_Int32 l32
= static_cast<sal_Int32
>(l
);
689 else if (PyFloat_Check (o
))
691 double d
= PyFloat_AsDouble (o
);
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
);
707 else if (PyList_Check (o
))
709 Py_ssize_t l
= PyList_Size (o
);
711 for (Py_ssize_t i
= 0; i
< l
; i
++)
713 s
[i
] = pyObject2Any (PyList_GetItem (o
, i
), mode
);
717 else if (!pyIterUnpack (o
, a
))
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()));
733 if( PyObject_IsInstance( o
, getTypeClass( runtime
).get() ) )
735 Type t
= PyType2Type( o
);
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
);
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
) );
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
);
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() );
819 Sequence
<Type
> interfaces
= invokeGetTypes(*this, o
);
820 if (interfaces
.getLength())
822 Adapter
*pAdapter
= new Adapter( o
, interfaces
);
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() )
843 OUString
const msg(lcl_ExceptionMessage(o
, nullptr));
844 throw RuntimeException(msg
);
851 Any
Runtime::extractUnoException( const PyRef
& excType
, const PyRef
&excValue
, const PyRef
&excTraceback
) const
855 if( excTraceback
.is() )
863 unoModule
= impl
->cargo
->getUnoModule();
865 catch (const Exception
&ei
)
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()) );
884 str
= "Couldn't find uno._uno_extract_printable_stacktrace";
889 str
= "Could not load uno.py, no stacktrace available";
890 if ( !e
.Message
.isEmpty() )
892 str
+= " (Error loading uno.py: " + e
.Message
+ ")";
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
);
910 PyRef
typeName( PyObject_Str( excType
.get() ), SAL_NO_ACQUIRE
);
913 buf
.appendAscii( PyUnicode_AsUTF8( typeName
.get() ) );
917 buf
.append( "no typename available" );
920 PyRef
valueRep( PyObject_Str( excValue
.get() ), SAL_NO_ACQUIRE
);
923 buf
.appendAscii( PyUnicode_AsUTF8( valueRep
.get()));
927 buf
.append( "Couldn't convert exception value to a string" );
929 buf
.append( ", traceback follows\n" );
937 buf
.append( ", no traceback available\n" );
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() );
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
960 tstate
= PyThreadState_New( interp
);
963 throw RuntimeException( "Couldn't create a pythreadstate" );
964 PyEval_AcquireThread( tstate
);
967 PyThreadAttach::~PyThreadAttach()
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();
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: */