Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / pyuno / source / module / pyuno_runtime.cxx
blob62b3861288c338bd1cabf4879bbb2b69a7086953
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/reflection/theCoreReflection.hpp>
41 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
42 #include <comphelper/sequence.hxx>
43 #include <comphelper/servicehelper.hxx>
44 #include <cppuhelper/exc_hlp.hxx>
46 #include <vector>
48 using com::sun::star::uno::Reference;
49 using com::sun::star::uno::XInterface;
50 using com::sun::star::uno::Any;
51 using com::sun::star::uno::TypeDescription;
52 using com::sun::star::uno::Sequence;
53 using com::sun::star::uno::Type;
54 using com::sun::star::uno::UNO_QUERY;
55 using com::sun::star::uno::Exception;
56 using com::sun::star::uno::RuntimeException;
57 using com::sun::star::uno::XComponentContext;
58 using com::sun::star::lang::WrappedTargetRuntimeException;
59 using com::sun::star::lang::XSingleServiceFactory;
60 using com::sun::star::lang::XUnoTunnel;
61 using com::sun::star::reflection::theCoreReflection;
62 using com::sun::star::reflection::InvocationTargetException;
63 using com::sun::star::script::Converter;
64 using com::sun::star::script::XTypeConverter;
65 using com::sun::star::script::XInvocation;
66 using com::sun::star::beans::XMaterialHolder;
67 using com::sun::star::beans::theIntrospection;
69 namespace pyuno
72 static PyTypeObject RuntimeImpl_Type =
74 PyVarObject_HEAD_INIT (&PyType_Type, 0)
75 "pyuno_runtime",
76 sizeof (RuntimeImpl),
78 RuntimeImpl::del,
79 #if PY_VERSION_HEX >= 0x03080000
80 0, // Py_ssize_t tp_vectorcall_offset
81 #else
82 nullptr, // printfunc tp_print
83 #endif
84 nullptr,
85 nullptr,
86 nullptr,
87 nullptr,
88 nullptr,
89 nullptr,
90 nullptr,
91 nullptr,
92 nullptr,
93 nullptr,
94 nullptr,
95 nullptr,
96 nullptr,
98 nullptr,
99 nullptr,
100 nullptr,
101 nullptr,
103 nullptr,
104 nullptr,
105 nullptr,
106 nullptr,
107 nullptr,
108 nullptr,
109 nullptr,
110 nullptr,
111 nullptr,
113 nullptr,
114 nullptr,
115 nullptr,
116 nullptr,
117 nullptr,
118 nullptr,
119 nullptr,
120 nullptr,
121 nullptr,
122 nullptr,
123 nullptr
125 #if PY_VERSION_HEX >= 0x03040000
126 , nullptr
127 #if PY_VERSION_HEX >= 0x03080000
128 , nullptr // vectorcallfunc tp_vectorcall
129 #endif
130 #endif
133 /*----------------------------------------------------------------------
134 Runtime implementation
135 -----------------------------------------------------------------------*/
136 /// @throws css::uno::RuntimeException
137 static void getRuntimeImpl( PyRef & globalDict, PyRef &runtimeImpl )
139 PyThreadState * state = PyThreadState_Get();
140 if( ! state )
142 throw RuntimeException( "python global interpreter must be held (thread must be attached)" );
145 PyObject* pModule = PyImport_AddModule("__main__");
147 if (!pModule)
149 throw RuntimeException("can't import __main__ module");
152 globalDict = PyRef( PyModule_GetDict(pModule));
154 if( ! globalDict.is() ) // FATAL !
156 throw RuntimeException("can't find __main__ module");
158 runtimeImpl = PyDict_GetItemString( globalDict.get() , "pyuno_runtime" );
161 /// @throws RuntimeException
162 static PyRef importUnoModule( )
164 // import the uno module
165 PyRef module( PyImport_ImportModule( "uno" ), SAL_NO_ACQUIRE, NOT_NULL );
166 if( PyErr_Occurred() )
168 PyRef excType, excValue, excTraceback;
169 PyErr_Fetch( reinterpret_cast<PyObject **>(&excType), reinterpret_cast<PyObject**>(&excValue), reinterpret_cast<PyObject**>(&excTraceback));
170 // As of Python 2.7 this gives a rather non-useful "<traceback object at 0xADDRESS>",
171 // but it is the best we can do in the absence of uno._uno_extract_printable_stacktrace
172 // Who knows, a future Python might print something better.
173 PyRef str( PyObject_Str( excTraceback.get() ), SAL_NO_ACQUIRE );
175 OUStringBuffer buf;
176 buf.append( "python object raised an unknown exception (" );
177 PyRef valueRep( PyObject_Repr( excValue.get() ), SAL_NO_ACQUIRE );
178 buf.appendAscii( PyStr_AsString( valueRep.get())).append( ", traceback follows\n" );
179 buf.appendAscii( PyStr_AsString( str.get() ) );
180 buf.append( ")" );
181 throw RuntimeException( buf.makeStringAndClear() );
183 PyRef dict( PyModule_GetDict( module.get() ) );
184 return dict;
187 static void readLoggingConfig( sal_Int32 *pLevel, FILE **ppFile )
189 *pLevel = LogLevel::NONE;
190 *ppFile = nullptr;
191 OUString fileName;
192 osl_getModuleURLFromFunctionAddress(
193 reinterpret_cast< oslGenericFunction >(readLoggingConfig),
194 &fileName.pData );
195 fileName = fileName.copy( fileName.lastIndexOf( '/' )+1 );
196 #ifdef MACOSX
197 fileName += "../" LIBO_ETC_FOLDER "/";
198 #endif
199 fileName += SAL_CONFIGFILE("pyuno" );
200 rtl::Bootstrap bootstrapHandle( fileName );
202 OUString str;
203 if( bootstrapHandle.getFrom( "PYUNO_LOGLEVEL", str ) )
205 if ( str == "NONE" )
206 *pLevel = LogLevel::NONE;
207 else if ( str == "CALL" )
208 *pLevel = LogLevel::CALL;
209 else if ( str == "ARGS" )
210 *pLevel = LogLevel::ARGS;
211 else
213 fprintf( stderr, "unknown loglevel %s\n",
214 OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
217 if( *pLevel > LogLevel::NONE )
219 *ppFile = stdout;
220 if( bootstrapHandle.getFrom( "PYUNO_LOGTARGET", str ) )
222 if ( str == "stdout" )
223 *ppFile = stdout;
224 else if ( str == "stderr" )
225 *ppFile = stderr;
226 else
228 oslProcessInfo data;
229 data.Size = sizeof( data );
230 osl_getProcessInfo(
231 nullptr , osl_Process_IDENTIFIER , &data );
232 osl_getSystemPathFromFileURL( str.pData, &str.pData);
233 OString o = OUStringToOString( str, osl_getThreadTextEncoding() );
234 o += ".";
235 o += OString::number( data.Ident );
237 *ppFile = fopen( o.getStr() , "w" );
238 if ( *ppFile )
240 // do not buffer (useful if e.g. analyzing a crash)
241 setvbuf( *ppFile, nullptr, _IONBF, 0 );
243 else
245 fprintf( stderr, "couldn't create file %s\n",
246 OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
254 /*-------------------------------------------------------------------
255 RuntimeImpl implementations
256 *-------------------------------------------------------------------*/
257 PyRef stRuntimeImpl::create( const Reference< XComponentContext > &ctx )
259 RuntimeImpl *me = PyObject_New (RuntimeImpl, &RuntimeImpl_Type);
260 if( ! me )
261 throw RuntimeException( "cannot instantiate pyuno::RuntimeImpl" );
262 me->cargo = nullptr;
263 // must use a different struct here, as the PyObject_New
264 // makes C++ unusable
265 RuntimeCargo *c = new RuntimeCargo;
266 readLoggingConfig( &(c->logLevel) , &(c->logFile) );
267 log( c, LogLevel::CALL, "Instantiating pyuno bridge" );
269 c->valid = true;
270 c->xContext = ctx;
271 c->xInvocation = Reference< XSingleServiceFactory > (
272 ctx->getServiceManager()->createInstanceWithContext(
273 "com.sun.star.script.Invocation",
274 ctx ),
275 css::uno::UNO_QUERY_THROW );
277 c->xTypeConverter = Converter::create(ctx);
278 if( ! c->xTypeConverter.is() )
279 throw RuntimeException( "pyuno: couldn't instantiate typeconverter service" );
281 c->xCoreReflection = theCoreReflection::get(ctx);
283 c->xAdapterFactory = css::script::InvocationAdapterFactory::create(ctx);
285 c->xIntrospection = theIntrospection::get(ctx);
287 Any a = ctx->getValueByName("/singletons/com.sun.star.reflection.theTypeDescriptionManager");
288 a >>= c->xTdMgr;
289 if( ! c->xTdMgr.is() )
290 throw RuntimeException( "pyuno: couldn't retrieve typedescriptionmanager" );
292 me->cargo =c;
293 return PyRef( reinterpret_cast< PyObject * > ( me ), SAL_NO_ACQUIRE );
296 void stRuntimeImpl::del(PyObject* self)
298 RuntimeImpl *me = reinterpret_cast< RuntimeImpl * > ( self );
299 if( me->cargo->logFile )
300 fclose( me->cargo->logFile );
301 delete me->cargo;
302 PyObject_Del (self);
306 void Runtime::initialize( const Reference< XComponentContext > & ctx )
308 PyRef globalDict, runtime;
309 getRuntimeImpl( globalDict , runtime );
310 RuntimeImpl *impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
312 if( runtime.is() && impl->cargo->valid )
314 throw RuntimeException("pyuno runtime has already been initialized before" );
316 PyRef keep( RuntimeImpl::create( ctx ) );
317 PyDict_SetItemString( globalDict.get(), "pyuno_runtime" , keep.get() );
318 Py_XINCREF( keep.get() );
322 bool Runtime::isInitialized()
324 PyRef globalDict, runtime;
325 getRuntimeImpl( globalDict , runtime );
326 RuntimeImpl *impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
327 return runtime.is() && impl->cargo->valid;
330 Runtime::Runtime()
331 : impl( nullptr )
333 PyRef globalDict, runtime;
334 getRuntimeImpl( globalDict , runtime );
335 if( ! runtime.is() )
337 throw RuntimeException(
338 "pyuno runtime is not initialized, "
339 "(the pyuno.bootstrap needs to be called before using any uno classes)" );
341 impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
342 Py_XINCREF( runtime.get() );
345 Runtime::Runtime( const Runtime & r )
347 impl = r.impl;
348 Py_XINCREF( reinterpret_cast< PyObject * >(impl) );
351 Runtime::~Runtime()
353 Py_XDECREF( reinterpret_cast< PyObject * >(impl) );
356 Runtime & Runtime::operator = ( const Runtime & r )
358 PyRef temp( reinterpret_cast< PyObject * >(r.impl) );
359 Py_XINCREF( temp.get() );
360 Py_XDECREF( reinterpret_cast< PyObject * >(impl) );
361 impl = r.impl;
362 return *this;
365 PyRef Runtime::any2PyObject (const Any &a ) const
367 if( ! impl->cargo->valid )
369 throw RuntimeException("pyuno runtime must be initialized before calling any2PyObject" );
372 switch (a.getValueTypeClass ())
374 case css::uno::TypeClass_VOID:
376 Py_INCREF (Py_None);
377 return PyRef(Py_None);
379 case css::uno::TypeClass_CHAR:
381 sal_Unicode c = *o3tl::forceAccess<sal_Unicode>(a);
382 return PyRef( PyUNO_char_new( c , *this ), SAL_NO_ACQUIRE );
384 case css::uno::TypeClass_BOOLEAN:
386 bool b;
387 if ((a >>= b) && b)
388 return Py_True;
389 else
390 return Py_False;
392 case css::uno::TypeClass_BYTE:
393 case css::uno::TypeClass_SHORT:
394 case css::uno::TypeClass_UNSIGNED_SHORT:
395 case css::uno::TypeClass_LONG:
397 sal_Int32 l = 0;
398 a >>= l;
399 return PyRef( PyLong_FromLong (l), SAL_NO_ACQUIRE );
401 case css::uno::TypeClass_UNSIGNED_LONG:
403 sal_uInt32 l = 0;
404 a >>= l;
405 return PyRef( PyLong_FromUnsignedLong (l), SAL_NO_ACQUIRE );
407 case css::uno::TypeClass_HYPER:
409 sal_Int64 l = 0;
410 a >>= l;
411 return PyRef( PyLong_FromLongLong (l), SAL_NO_ACQUIRE);
413 case css::uno::TypeClass_UNSIGNED_HYPER:
415 sal_uInt64 l = 0;
416 a >>= l;
417 return PyRef( PyLong_FromUnsignedLongLong (l), SAL_NO_ACQUIRE);
419 case css::uno::TypeClass_FLOAT:
421 float f = 0.0;
422 a >>= f;
423 return PyRef(PyFloat_FromDouble (f), SAL_NO_ACQUIRE);
425 case css::uno::TypeClass_DOUBLE:
427 double d = 0.0;
428 a >>= d;
429 return PyRef( PyFloat_FromDouble (d), SAL_NO_ACQUIRE);
431 case css::uno::TypeClass_STRING:
433 OUString tmp_ostr;
434 a >>= tmp_ostr;
435 return ustring2PyUnicode( tmp_ostr );
437 case css::uno::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(), t.getTypeClass(), *this),
445 SAL_NO_ACQUIRE);
447 case css::uno::TypeClass_ANY:
449 //I don't think this can happen.
450 Py_INCREF (Py_None);
451 return Py_None;
453 case css::uno::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 throw RuntimeException( "Any carries enum " + a.getValueType().getTypeName() +
473 " with invalid value " + OUString::number(l) );
475 case css::uno::TypeClass_EXCEPTION:
476 case css::uno::TypeClass_STRUCT:
478 PyRef excClass = getClass( a.getValueType().getTypeName(), *this );
479 PyRef value = PyUNOStruct_new( a, getImpl()->cargo->xInvocation );
480 PyRef argsTuple( PyTuple_New( 1 ) , SAL_NO_ACQUIRE, NOT_NULL );
481 PyTuple_SetItem( argsTuple.get() , 0 , value.getAcquired() );
482 PyRef ret( PyObject_CallObject( excClass.get() , argsTuple.get() ), SAL_NO_ACQUIRE );
483 if( ! ret.is() )
485 throw RuntimeException( "Couldn't instantiate python representation of structured UNO type " +
486 a.getValueType().getTypeName() );
489 if( auto e = o3tl::tryAccess<css::uno::Exception>(a) )
491 // add the message in a standard python way !
492 PyRef args( PyTuple_New( 1 ), SAL_NO_ACQUIRE, NOT_NULL );
494 PyRef pymsg = ustring2PyString( e->Message );
495 PyTuple_SetItem( args.get(), 0 , pymsg.getAcquired() );
496 // the exception base functions want to have an "args" tuple,
497 // which contains the message
498 PyObject_SetAttrString( ret.get(), "args", args.get() );
500 return ret;
502 case css::uno::TypeClass_SEQUENCE:
504 Sequence<Any> s;
506 Sequence< sal_Int8 > byteSequence;
507 if( a >>= byteSequence )
509 // byte sequence is treated in a special way because of performance reasons
510 // @since 0.9.2
511 return PyRef( PyUNO_ByteSequence_new( byteSequence, *this ), SAL_NO_ACQUIRE );
513 else
515 Reference< XTypeConverter > tc = getImpl()->cargo->xTypeConverter;
516 tc->convertTo (a, cppu::UnoType<decltype(s)>::get()) >>= s;
517 PyRef tuple( PyTuple_New (s.getLength()), SAL_NO_ACQUIRE, NOT_NULL);
518 int i=0;
521 for ( i = 0; i < s.getLength (); i++)
523 PyRef element = any2PyObject (tc->convertTo (s[i], s[i].getValueType() ));
524 OSL_ASSERT( element.is() );
525 PyTuple_SetItem( tuple.get(), i, element.getAcquired() );
528 catch( css::uno::Exception & )
530 for( ; i < s.getLength() ; i ++ )
532 Py_INCREF( Py_None );
533 PyTuple_SetItem( tuple.get(), i, Py_None );
535 throw;
537 return tuple;
540 case css::uno::TypeClass_INTERFACE:
542 Reference<XInterface> tmp_interface;
543 a >>= tmp_interface;
544 if (!tmp_interface.is ())
545 return Py_None;
547 return PyUNO_new( a, getImpl()->cargo->xInvocation );
549 default:
551 throw RuntimeException( "Unknown UNO type class " + OUString::number(static_cast<int>(a.getValueTypeClass())) );
556 static Sequence< Type > invokeGetTypes( const Runtime & r , PyObject * o )
558 Sequence< Type > ret;
560 PyRef method( PyObject_GetAttrString( o , "getTypes" ), SAL_NO_ACQUIRE );
561 raiseInvocationTargetExceptionWhenNeeded( r );
562 if( method.is() && PyCallable_Check( method.get() ) )
564 PyRef types( PyObject_CallObject( method.get(), nullptr ) , SAL_NO_ACQUIRE );
565 raiseInvocationTargetExceptionWhenNeeded( r );
566 if( types.is() && PyTuple_Check( types.get() ) )
568 int size = PyTuple_Size( types.get() );
570 // add the XUnoTunnel interface for uno object identity concept (hack)
571 ret.realloc( size + 1 );
572 for( int i = 0 ; i < size ; i ++ )
574 Any a = r.pyObject2Any(PyTuple_GetItem(types.get(),i));
575 a >>= ret[i];
577 ret[size] = cppu::UnoType<css::lang::XUnoTunnel>::get();
580 return ret;
583 static OUString
584 lcl_ExceptionMessage(PyObject *const o, OUString const*const pWrapped)
586 OUStringBuffer buf;
587 buf.append("Couldn't convert ");
588 PyRef reprString( PyObject_Str(o), SAL_NO_ACQUIRE );
589 buf.appendAscii( PyStr_AsString(reprString.get()) );
590 buf.append(" to a UNO type");
591 if (pWrapped)
593 buf.append("; caught exception: ");
594 buf.append(*pWrapped);
596 return buf.makeStringAndClear();
599 // For Python 2.7 - see https://bugs.python.org/issue24161
600 // Fills aSeq and returns true if pObj is a valid iterator
601 bool Runtime::pyIterUnpack( PyObject *const pObj, Any &a ) const
603 if( !PyIter_Check( pObj ))
604 return false;
606 PyObject *pItem = PyIter_Next( pObj );
607 if( !pItem )
609 if( PyErr_Occurred() )
611 PyErr_Clear();
612 return false;
614 return true;
617 ::std::vector<Any> items;
620 PyRef rItem( pItem, SAL_NO_ACQUIRE );
621 items.push_back( pyObject2Any( rItem.get() ) );
622 pItem = PyIter_Next( pObj );
624 while( pItem );
625 a <<= comphelper::containerToSequence(items);
626 return true;
629 Any Runtime::pyObject2Any ( const PyRef & source, enum ConversionMode mode ) const
631 if( ! impl->cargo->valid )
633 throw RuntimeException("pyuno runtime must be initialized before calling any2PyObject" );
636 Any a;
637 PyObject *o = source.get();
638 if( Py_None == o )
642 // In Python 3, there is no PyInt type.
643 #if PY_MAJOR_VERSION < 3
644 else if (PyInt_Check (o))
646 if( o == Py_True )
648 a <<= true;
650 else if ( o == Py_False )
652 a <<= false;
654 else
656 sal_Int32 l = (sal_Int32) PyLong_AsLong( o );
657 if( l < 128 && l >= -128 )
659 sal_Int8 b = (sal_Int8 ) l;
660 a <<= b;
662 else if( l <= 0x7fff && l >= -0x8000 )
664 sal_Int16 s = (sal_Int16) l;
665 a <<= s;
667 else
669 a <<= l;
673 #endif /* PY_MAJOR_VERSION < 3 */
674 else if (PyLong_Check (o))
676 #if PY_MAJOR_VERSION >= 3
677 // Convert the Python 3 booleans that are actually of type PyLong.
678 if(o == Py_True)
680 a <<= true;
682 else if(o == Py_False)
684 a <<= false;
686 else
688 #endif /* PY_MAJOR_VERSION >= 3 */
689 sal_Int64 l = static_cast<sal_Int64>(PyLong_AsLong (o));
690 if( l < 128 && l >= -128 )
692 sal_Int8 b = static_cast<sal_Int8>(l);
693 a <<= b;
695 else if( l <= 0x7fff && l >= -0x8000 )
697 sal_Int16 s = static_cast<sal_Int16>(l);
698 a <<= s;
700 else if( l <= SAL_CONST_INT64(0x7fffffff) &&
701 l >= -SAL_CONST_INT64(0x80000000) )
703 sal_Int32 l32 = static_cast<sal_Int32>(l);
704 a <<= l32;
706 else
708 a <<= l;
710 #if PY_MAJOR_VERSION >= 3
712 #endif
714 else if (PyFloat_Check (o))
716 double d = PyFloat_AsDouble (o);
717 a <<= d;
719 else if (PyStrBytes_Check(o) || PyUnicode_Check(o))
721 a <<= pyString2ustring(o);
723 else if (PyTuple_Check (o))
725 Sequence<Any> s (PyTuple_Size (o));
726 for (Py_ssize_t i = 0; i < PyTuple_Size (o); i++)
728 s[i] = pyObject2Any (PyTuple_GetItem (o, i), mode );
730 a <<= s;
732 else if (PyList_Check (o))
734 Py_ssize_t l = PyList_Size (o);
735 Sequence<Any> s (l);
736 for (Py_ssize_t i = 0; i < l; i++)
738 s[i] = pyObject2Any (PyList_GetItem (o, i), mode );
740 a <<= s;
742 else if (!pyIterUnpack (o, a))
744 Runtime runtime;
745 // should be removed, in case ByteSequence gets derived from String
746 if( PyObject_IsInstance( o, getByteSequenceClass( runtime ).get() ) )
748 PyRef str(PyObject_GetAttrString( o , "value" ),SAL_NO_ACQUIRE);
749 Sequence< sal_Int8 > seq;
750 if( PyStrBytes_Check( str.get() ) )
752 seq = Sequence<sal_Int8 > (
753 reinterpret_cast<sal_Int8*>(PyStrBytes_AsString(str.get())), PyStrBytes_Size(str.get()));
755 a <<= seq;
757 else
758 if( PyObject_IsInstance( o, getTypeClass( runtime ).get() ) )
760 Type t = PyType2Type( o );
761 a <<= t;
763 else if( PyObject_IsInstance( o, getEnumClass( runtime ).get() ) )
765 a = PyEnum2Enum( o );
767 else if( isInstanceOfStructOrException( o ) )
769 PyRef struc(PyObject_GetAttrString( o , "value" ),SAL_NO_ACQUIRE);
770 PyUNO * obj = reinterpret_cast<PyUNO*>(struc.get());
771 Reference< XMaterialHolder > holder( obj->members->xInvocation, UNO_QUERY );
772 if( !holder.is( ) )
774 throw RuntimeException(
775 "struct or exception wrapper does not support XMaterialHolder" );
778 a = holder->getMaterial();
781 else if( PyObject_IsInstance( o, getPyUnoClass().get() ) )
783 PyUNO* o_pi = reinterpret_cast<PyUNO*>(o);
784 a = o_pi->members->wrappedObject;
786 else if( PyObject_IsInstance( o, getPyUnoStructClass().get() ) )
788 PyUNO* o_pi = reinterpret_cast<PyUNO*>(o);
789 Reference<XMaterialHolder> my_mh (o_pi->members->xInvocation, css::uno::UNO_QUERY_THROW);
790 a = my_mh->getMaterial();
792 else if( PyObject_IsInstance( o, getCharClass( runtime ).get() ) )
794 a <<= PyChar2Unicode( o );
796 else if( PyObject_IsInstance( o, getAnyClass( runtime ).get() ) )
798 if( ACCEPT_UNO_ANY != mode )
800 throw RuntimeException(
801 "uno.Any instance not accepted during method call, "
802 "use uno.invoke instead" );
805 a = pyObject2Any( PyRef( PyObject_GetAttrString( o , "value" ), SAL_NO_ACQUIRE) );
806 Type t;
807 pyObject2Any( PyRef( PyObject_GetAttrString( o, "type" ), SAL_NO_ACQUIRE ) ) >>= t;
811 a = getImpl()->cargo->xTypeConverter->convertTo( a, t );
813 catch( const css::uno::Exception & e )
815 css::uno::Any anyEx = cppu::getCaughtException();
816 throw WrappedTargetRuntimeException(
817 e.Message, e.Context, anyEx);
821 else
823 Reference< XInterface > mappedObject;
824 Reference< XInvocation > adapterObject;
826 // instance already mapped out to the world ?
827 PyRef2Adapter::iterator ii = impl->cargo->mappedObjects.find( PyRef( o ) );
828 if( ii != impl->cargo->mappedObjects.end() )
830 adapterObject = ii->second;
833 if( adapterObject.is() )
835 // object got already bridged !
836 auto pAdapter = comphelper::getUnoTunnelImplementation<Adapter>(adapterObject);
838 mappedObject = impl->cargo->xAdapterFactory->createAdapter(
839 adapterObject, pAdapter->getWrappedTypes() );
841 else
843 try {
844 Sequence<Type> interfaces = invokeGetTypes(*this, o);
845 if (interfaces.getLength())
847 Adapter *pAdapter = new Adapter( o, interfaces );
848 mappedObject =
849 getImpl()->cargo->xAdapterFactory->createAdapter(
850 pAdapter, interfaces );
852 // keep a list of exported objects to ensure object identity !
853 impl->cargo->mappedObjects[ PyRef(o) ] =
854 css::uno::WeakReference< XInvocation > ( pAdapter );
856 } catch (InvocationTargetException const& e) {
857 OUString const msg(lcl_ExceptionMessage(o, &e.Message));
858 throw WrappedTargetRuntimeException( // re-wrap that
859 msg, e.Context, e.TargetException);
862 if( mappedObject.is() )
864 a <<= mappedObject;
866 else
868 OUString const msg(lcl_ExceptionMessage(o, nullptr));
869 throw RuntimeException(msg);
873 return a;
876 Any Runtime::extractUnoException( const PyRef & excType, const PyRef &excValue, const PyRef &excTraceback) const
878 OUString str;
879 Any ret;
880 if( excTraceback.is() )
882 Exception e;
883 PyRef unoModule;
884 if ( impl )
888 unoModule = impl->cargo->getUnoModule();
890 catch (const Exception &ei)
892 e=ei;
895 if( unoModule.is() )
897 PyRef extractTraceback(
898 PyDict_GetItemString(unoModule.get(),"_uno_extract_printable_stacktrace" ) );
900 if( PyCallable_Check(extractTraceback.get()) )
902 PyRef args( PyTuple_New( 1), SAL_NO_ACQUIRE, NOT_NULL );
903 PyTuple_SetItem( args.get(), 0, excTraceback.getAcquired() );
904 PyRef pyStr( PyObject_CallObject( extractTraceback.get(),args.get() ), SAL_NO_ACQUIRE);
905 str = OUString::createFromAscii( PyStr_AsString(pyStr.get()) );
907 else
909 str = "Couldn't find uno._uno_extract_printable_stacktrace";
912 else
914 str = "Could not load uno.py, no stacktrace available";
915 if ( !e.Message.isEmpty() )
917 str += " (Error loading uno.py: " + e.Message + ")";
922 else
924 // it may occur, that no traceback is given (e.g. only native code below)
925 str = "no traceback available";
928 if( isInstanceOfStructOrException( excValue.get() ) )
930 ret = pyObject2Any( excValue );
932 else
934 OUStringBuffer buf;
935 PyRef typeName( PyObject_Str( excType.get() ), SAL_NO_ACQUIRE );
936 if( typeName.is() )
938 buf.appendAscii( PyStr_AsString( typeName.get() ) );
940 else
942 buf.append( "no typename available" );
944 buf.append( ": " );
945 PyRef valueRep( PyObject_Str( excValue.get() ), SAL_NO_ACQUIRE );
946 if( valueRep.is() )
948 buf.appendAscii( PyStr_AsString( valueRep.get()));
950 else
952 buf.append( "Couldn't convert exception value to a string" );
954 buf.append( ", traceback follows\n" );
955 if( !str.isEmpty() )
957 buf.append( str );
958 buf.append( "\n" );
960 else
962 buf.append( ", no traceback available\n" );
964 RuntimeException e;
965 e.Message = buf.makeStringAndClear();
966 #if OSL_DEBUG_LEVEL > 0
967 fprintf( stderr, "Python exception: %s\n",
968 OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr() );
969 #endif
970 ret <<= e;
972 return ret;
976 PyThreadAttach::PyThreadAttach( PyInterpreterState *interp)
978 tstate = PyThreadState_New( interp );
979 if( !tstate )
980 throw RuntimeException( "Couldn't create a pythreadstate" );
981 PyEval_AcquireThread( tstate);
984 PyThreadAttach::~PyThreadAttach()
986 PyThreadState_Clear( tstate );
987 PyEval_ReleaseThread( tstate );
988 PyThreadState_Delete( tstate );
991 PyThreadDetach::PyThreadDetach()
993 tstate = PyThreadState_Get();
994 PyEval_ReleaseThread( tstate );
997 /** Acquires the global interpreter lock again
1000 PyThreadDetach::~PyThreadDetach()
1002 PyEval_AcquireThread( tstate );
1006 PyRef const & RuntimeCargo::getUnoModule()
1008 if( ! dictUnoModule.is() )
1010 dictUnoModule = importUnoModule();
1012 return dictUnoModule;
1016 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */