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_features.h>
21 #include <config_folders.h>
23 #include "pyuno_impl.hxx"
25 #include <osl/diagnose.h>
26 #include <osl/thread.h>
27 #include <osl/module.h>
28 #include <osl/process.h>
29 #include <rtl/strbuf.hxx>
30 #include <rtl/ustrbuf.hxx>
31 #include <rtl/bootstrap.hxx>
33 #include <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/script/Converter.hpp>
39 #include <com/sun/star/script/InvocationAdapterFactory.hpp>
40 #include <com/sun/star/reflection/theCoreReflection.hpp>
43 using com::sun::star::uno::Reference
;
44 using com::sun::star::uno::XInterface
;
45 using com::sun::star::uno::Any
;
46 using com::sun::star::uno::TypeDescription
;
47 using com::sun::star::uno::Sequence
;
48 using com::sun::star::uno::Type
;
49 using com::sun::star::uno::UNO_QUERY
;
50 using com::sun::star::uno::Exception
;
51 using com::sun::star::uno::RuntimeException
;
52 using com::sun::star::uno::XComponentContext
;
53 using com::sun::star::lang::WrappedTargetRuntimeException
;
54 using com::sun::star::lang::XSingleServiceFactory
;
55 using com::sun::star::lang::XUnoTunnel
;
56 using com::sun::star::reflection::theCoreReflection
;
57 using com::sun::star::reflection::XIdlReflection
;
58 using com::sun::star::reflection::InvocationTargetException
;
59 using com::sun::star::script::Converter
;
60 using com::sun::star::script::XTypeConverter
;
61 using com::sun::star::script::XInvocationAdapterFactory2
;
62 using com::sun::star::script::XInvocation
;
63 using com::sun::star::beans::XMaterialHolder
;
64 using com::sun::star::beans::XIntrospection
;
65 using com::sun::star::beans::theIntrospection
;
72 static PyTypeObject RuntimeImpl_Type
=
74 PyVarObject_HEAD_INIT (&PyType_Type
, 0)
78 (destructor
) RuntimeImpl::del
,
120 #if PY_VERSION_HEX >= 0x02060000
123 #if PY_VERSION_HEX >= 0x03040000
128 /*----------------------------------------------------------------------
129 Runtime implementation
130 -----------------------------------------------------------------------*/
131 static void getRuntimeImpl( PyRef
& globalDict
, PyRef
&runtimeImpl
)
132 throw ( com::sun::star::uno::RuntimeException
)
134 PyThreadState
* state
= PyThreadState_Get();
137 throw RuntimeException( "python global interpreter must be held (thread must be attached)" );
140 PyObject
* pModule
= PyImport_AddModule("__main__");
144 throw RuntimeException("can't import __main__ module");
147 globalDict
= PyRef( PyModule_GetDict(pModule
));
149 if( ! globalDict
.is() ) // FATAL !
151 throw RuntimeException("can't find __main__ module");
153 runtimeImpl
= PyDict_GetItemString( globalDict
.get() , "pyuno_runtime" );
156 static PyRef
importUnoModule( ) throw ( RuntimeException
)
158 // import the uno module
159 PyRef
module( PyImport_ImportModule( "uno" ), SAL_NO_ACQUIRE
, NOT_NULL
);
160 if( PyErr_Occurred() )
162 PyRef excType
, excValue
, excTraceback
;
163 PyErr_Fetch( reinterpret_cast<PyObject
**>(&excType
), reinterpret_cast<PyObject
**>(&excValue
), reinterpret_cast<PyObject
**>(&excTraceback
));
164 // As of Python 2.7 this gives a rather non-useful "<traceback object at 0xADDRESS>",
165 // but it is the best we can do in the absence of uno._uno_extract_printable_stacktrace
166 // Who knows, a future Python might print something better.
167 PyRef
str( PyObject_Str( excTraceback
.get() ), SAL_NO_ACQUIRE
);
170 buf
.appendAscii( "python object raised an unknown exception (" );
171 PyRef
valueRep( PyObject_Repr( excValue
.get() ), SAL_NO_ACQUIRE
);
172 buf
.appendAscii( PyStr_AsString( valueRep
.get())).appendAscii( ", traceback follows\n" );
173 buf
.appendAscii( PyStr_AsString( str
.get() ) );
174 buf
.appendAscii( ")" );
175 throw RuntimeException( buf
.makeStringAndClear() );
177 PyRef
dict( PyModule_GetDict( module
.get() ) );
181 static void readLoggingConfig( sal_Int32
*pLevel
, FILE **ppFile
)
183 *pLevel
= LogLevel::NONE
;
186 osl_getModuleURLFromFunctionAddress(
187 reinterpret_cast< oslGenericFunction
>(readLoggingConfig
),
189 fileName
= fileName
.copy( fileName
.lastIndexOf( '/' )+1 );
191 fileName
+= "../" LIBO_ETC_FOLDER
"/";
193 fileName
+= SAL_CONFIGFILE("pyuno" );
194 rtl::Bootstrap
bootstrapHandle( fileName
);
197 if( bootstrapHandle
.getFrom( "PYUNO_LOGLEVEL", str
) )
200 *pLevel
= LogLevel::NONE
;
201 else if ( str
== "CALL" )
202 *pLevel
= LogLevel::CALL
;
203 else if ( str
== "ARGS" )
204 *pLevel
= LogLevel::ARGS
;
207 fprintf( stderr
, "unknown loglevel %s\n",
208 OUStringToOString( str
, RTL_TEXTENCODING_UTF8
).getStr() );
211 if( *pLevel
> LogLevel::NONE
)
214 if( bootstrapHandle
.getFrom( "PYUNO_LOGTARGET", str
) )
216 if ( str
== "stdout" )
218 else if ( str
== "stderr" )
223 data
.Size
= sizeof( data
);
225 0 , osl_Process_IDENTIFIER
, &data
);
226 osl_getSystemPathFromFileURL( str
.pData
, &str
.pData
);
227 OString o
= OUStringToOString( str
, osl_getThreadTextEncoding() );
229 o
+= OString::number( data
.Ident
);
231 *ppFile
= fopen( o
.getStr() , "w" );
234 // do not buffer (useful if e.g. analyzing a crash)
235 setvbuf( *ppFile
, 0, _IONBF
, 0 );
239 fprintf( stderr
, "couldn't create file %s\n",
240 OUStringToOString( str
, RTL_TEXTENCODING_UTF8
).getStr() );
248 /*-------------------------------------------------------------------
249 RuntimeImpl implementations
250 *-------------------------------------------------------------------*/
251 PyRef
stRuntimeImpl::create( const Reference
< XComponentContext
> &ctx
)
252 throw( com::sun::star::uno::RuntimeException
)
254 RuntimeImpl
*me
= PyObject_New (RuntimeImpl
, &RuntimeImpl_Type
);
256 throw RuntimeException( "cannot instantiate pyuno::RuntimeImpl" );
258 // must use a different struct here, as the PyObject_New
259 // makes C++ unusable
260 RuntimeCargo
*c
= new RuntimeCargo();
261 readLoggingConfig( &(c
->logLevel
) , &(c
->logFile
) );
262 log( c
, LogLevel::CALL
, "Instantiating pyuno bridge" );
266 c
->xInvocation
= Reference
< XSingleServiceFactory
> (
267 ctx
->getServiceManager()->createInstanceWithContext(
268 OUString( "com.sun.star.script.Invocation" ),
271 if( ! c
->xInvocation
.is() )
272 throw RuntimeException( "pyuno: couldn't instantiate invocation service" );
274 c
->xTypeConverter
= Converter::create(ctx
);
275 if( ! c
->xTypeConverter
.is() )
276 throw RuntimeException( "pyuno: couldn't instantiate typeconverter service" );
278 c
->xCoreReflection
= theCoreReflection::get(ctx
);
280 c
->xAdapterFactory
= css::script::InvocationAdapterFactory::create(ctx
);
282 c
->xIntrospection
= theIntrospection::get(ctx
);
284 Any a
= ctx
->getValueByName("/singletons/com.sun.star.reflection.theTypeDescriptionManager");
286 if( ! c
->xTdMgr
.is() )
287 throw RuntimeException( "pyuno: couldn't retrieve typedescriptionmanager" );
290 return PyRef( reinterpret_cast< PyObject
* > ( me
), SAL_NO_ACQUIRE
);
293 void stRuntimeImpl::del(PyObject
* self
)
295 RuntimeImpl
*me
= reinterpret_cast< RuntimeImpl
* > ( self
);
296 if( me
->cargo
->logFile
)
297 fclose( me
->cargo
->logFile
);
303 void Runtime::initialize( const Reference
< XComponentContext
> & ctx
)
304 throw ( RuntimeException
)
306 PyRef globalDict
, runtime
;
307 getRuntimeImpl( globalDict
, runtime
);
308 RuntimeImpl
*impl
= reinterpret_cast< RuntimeImpl
* > (runtime
.get());
310 if( runtime
.is() && impl
->cargo
->valid
)
312 throw RuntimeException("pyuno runtime has already been initialized before" );
314 PyRef
keep( RuntimeImpl::create( ctx
) );
315 PyDict_SetItemString( globalDict
.get(), "pyuno_runtime" , keep
.get() );
316 Py_XINCREF( keep
.get() );
320 bool Runtime::isInitialized() throw ( RuntimeException
)
322 PyRef globalDict
, runtime
;
323 getRuntimeImpl( globalDict
, runtime
);
324 RuntimeImpl
*impl
= reinterpret_cast< RuntimeImpl
* > (runtime
.get());
325 return runtime
.is() && impl
->cargo
->valid
;
328 Runtime::Runtime() throw( RuntimeException
)
331 PyRef globalDict
, runtime
;
332 getRuntimeImpl( globalDict
, runtime
);
335 throw RuntimeException(
336 "pyuno runtime is not initialized, "
337 "(the pyuno.bootstrap needs to be called before using any uno classes)" );
339 impl
= reinterpret_cast< RuntimeImpl
* > (runtime
.get());
340 Py_XINCREF( runtime
.get() );
343 Runtime::Runtime( const Runtime
& r
)
346 Py_XINCREF( reinterpret_cast< PyObject
* >(impl
) );
351 Py_XDECREF( reinterpret_cast< PyObject
* >(impl
) );
354 Runtime
& Runtime::operator = ( const Runtime
& r
)
356 PyRef
temp( reinterpret_cast< PyObject
* >(r
.impl
) );
357 Py_XINCREF( temp
.get() );
358 Py_XDECREF( reinterpret_cast< PyObject
* >(impl
) );
363 PyRef
Runtime::any2PyObject (const Any
&a
) const
364 throw ( com::sun::star::script::CannotConvertException
,
365 com::sun::star::lang::IllegalArgumentException
,
368 if( ! impl
->cargo
->valid
)
370 throw RuntimeException("pyuno runtime must be initialized before calling any2PyObject" );
373 switch (a
.getValueTypeClass ())
375 case typelib_TypeClass_VOID
:
378 return PyRef(Py_None
);
380 case typelib_TypeClass_CHAR
:
382 sal_Unicode c
= *static_cast<sal_Unicode
const *>(a
.getValue());
383 return PyRef( PyUNO_char_new( c
, *this ), SAL_NO_ACQUIRE
);
385 case typelib_TypeClass_BOOLEAN
:
393 case typelib_TypeClass_BYTE
:
394 case typelib_TypeClass_SHORT
:
395 case typelib_TypeClass_UNSIGNED_SHORT
:
396 case typelib_TypeClass_LONG
:
400 return PyRef( PyLong_FromLong (l
), SAL_NO_ACQUIRE
);
402 case typelib_TypeClass_UNSIGNED_LONG
:
406 return PyRef( PyLong_FromUnsignedLong (l
), SAL_NO_ACQUIRE
);
408 case typelib_TypeClass_HYPER
:
412 return PyRef( PyLong_FromLongLong (l
), SAL_NO_ACQUIRE
);
414 case typelib_TypeClass_UNSIGNED_HYPER
:
418 return PyRef( PyLong_FromUnsignedLongLong (l
), SAL_NO_ACQUIRE
);
420 case typelib_TypeClass_FLOAT
:
424 return PyRef(PyFloat_FromDouble (f
), SAL_NO_ACQUIRE
);
426 case typelib_TypeClass_DOUBLE
:
430 return PyRef( PyFloat_FromDouble (d
), SAL_NO_ACQUIRE
);
432 case typelib_TypeClass_STRING
:
436 return ustring2PyUnicode( tmp_ostr
);
438 case typelib_TypeClass_TYPE
:
442 OString o
= OUStringToOString( t
.getTypeName(), RTL_TEXTENCODING_ASCII_US
);
445 o
.getStr(), (com::sun::star::uno::TypeClass
)t
.getTypeClass(), *this),
448 case typelib_TypeClass_ANY
:
450 //I don't think this can happen.
454 case typelib_TypeClass_ENUM
:
456 sal_Int32 l
= *static_cast<sal_Int32
const *>(a
.getValue());
457 TypeDescription
desc( a
.getValueType() );
461 typelib_EnumTypeDescription
*pEnumDesc
=
462 reinterpret_cast<typelib_EnumTypeDescription
*>(desc
.get());
463 for( int i
= 0 ; i
< pEnumDesc
->nEnumValues
; i
++ )
465 if( pEnumDesc
->pEnumValues
[i
] == l
)
467 OString v
= OUStringToOString( pEnumDesc
->ppEnumNames
[i
], RTL_TEXTENCODING_ASCII_US
);
468 OString e
= OUStringToOString( pEnumDesc
->aBase
.pTypeName
, RTL_TEXTENCODING_ASCII_US
);
469 return PyRef( PyUNO_Enum_new(e
.getStr(),v
.getStr(), *this ), SAL_NO_ACQUIRE
);
474 buf
.appendAscii( "Any carries enum " );
475 buf
.append( a
.getValueType().getTypeName());
476 buf
.appendAscii( " with invalid value " ).append( l
);
477 throw RuntimeException( buf
.makeStringAndClear() );
479 case typelib_TypeClass_EXCEPTION
:
480 case typelib_TypeClass_STRUCT
:
482 PyRef excClass
= getClass( a
.getValueType().getTypeName(), *this );
483 PyRef value
= PyRef( PyUNO_new_UNCHECKED (a
, getImpl()->cargo
->xInvocation
), SAL_NO_ACQUIRE
);
484 PyRef
argsTuple( PyTuple_New( 1 ) , SAL_NO_ACQUIRE
, NOT_NULL
);
485 PyTuple_SetItem( argsTuple
.get() , 0 , value
.getAcquired() );
486 PyRef
ret( PyObject_CallObject( excClass
.get() , argsTuple
.get() ), SAL_NO_ACQUIRE
);
490 buf
.appendAscii( "Couldn't instantiate python representation of structered UNO type " );
491 buf
.append( a
.getValueType().getTypeName() );
492 throw RuntimeException( buf
.makeStringAndClear() );
495 if( com::sun::star::uno::TypeClass_EXCEPTION
== a
.getValueTypeClass() )
497 // add the message in a standard python way !
498 PyRef
args( PyTuple_New( 1 ), SAL_NO_ACQUIRE
, NOT_NULL
);
500 // assuming that the Message is always the first member, wuuuu
501 void const *pData
= a
.getValue();
502 OUString message
= *static_cast<OUString
const *>(pData
);
503 PyRef pymsg
= ustring2PyString( message
);
504 PyTuple_SetItem( args
.get(), 0 , pymsg
.getAcquired() );
505 // the exception base functions want to have an "args" tuple,
506 // which contains the message
507 PyObject_SetAttrString( ret
.get(), "args", args
.get() );
511 case typelib_TypeClass_SEQUENCE
:
515 Sequence
< sal_Int8
> byteSequence
;
516 if( a
>>= byteSequence
)
518 // byte sequence is treated in a special way because of peformance reasons
520 return PyRef( PyUNO_ByteSequence_new( byteSequence
, *this ), SAL_NO_ACQUIRE
);
524 Reference
< XTypeConverter
> tc
= getImpl()->cargo
->xTypeConverter
;
525 Reference
< XSingleServiceFactory
> ssf
= getImpl()->cargo
->xInvocation
;
526 tc
->convertTo (a
, cppu::UnoType
<decltype(s
)>::get()) >>= s
;
527 PyRef
tuple( PyTuple_New (s
.getLength()), SAL_NO_ACQUIRE
, NOT_NULL
);
531 for ( i
= 0; i
< s
.getLength (); i
++)
534 element
= any2PyObject (tc
->convertTo (s
[i
], s
[i
].getValueType() ));
535 OSL_ASSERT( element
.is() );
536 PyTuple_SetItem( tuple
.get(), i
, element
.getAcquired() );
539 catch( com::sun::star::uno::Exception
& )
541 for( ; i
< s
.getLength() ; i
++ )
543 Py_INCREF( Py_None
);
544 PyTuple_SetItem( tuple
.get(), i
, Py_None
);
551 case typelib_TypeClass_INTERFACE
:
553 // fdo#46678 must unlock GIL because getSomething could acquire locks,
554 // and queryInterface too...
558 Reference
<XUnoTunnel
> tunnel
;
562 sal_Int64 that
= tunnel
->getSomething( ::pyuno::Adapter::getUnoTunnelImplementationId() );
564 return reinterpret_cast<Adapter
*>(that
)->getWrappedObject();
567 //This is just like the struct case:
568 return PyRef( PyUNO_new (a
, getImpl()->cargo
->xInvocation
), SAL_NO_ACQUIRE
);
573 buf
.appendAscii( "Unknown UNO type class " );
574 buf
.append( (sal_Int32
) a
.getValueTypeClass() );
575 throw RuntimeException(buf
.makeStringAndClear( ) );
580 static Sequence
< Type
> invokeGetTypes( const Runtime
& r
, PyObject
* o
)
582 Sequence
< Type
> ret
;
584 PyRef
method( PyObject_GetAttrString( o
, "getTypes" ), SAL_NO_ACQUIRE
);
585 raiseInvocationTargetExceptionWhenNeeded( r
);
586 if( method
.is() && PyCallable_Check( method
.get() ) )
588 PyRef
types( PyObject_CallObject( method
.get(), 0 ) , SAL_NO_ACQUIRE
);
589 raiseInvocationTargetExceptionWhenNeeded( r
);
590 if( types
.is() && PyTuple_Check( types
.get() ) )
592 int size
= PyTuple_Size( types
.get() );
594 // add the XUnoTunnel interface for uno object identity concept (hack)
595 ret
.realloc( size
+ 1 );
596 for( int i
= 0 ; i
< size
; i
++ )
598 Any a
= r
.pyObject2Any(PyTuple_GetItem(types
.get(),i
));
601 ret
[size
] = cppu::UnoType
<com::sun::star::lang::XUnoTunnel
>::get();
608 lcl_ExceptionMessage(PyObject
*const o
, OUString
const*const pWrapped
)
611 buf
.appendAscii("Couldn't convert ");
612 PyRef
reprString( PyObject_Str(o
), SAL_NO_ACQUIRE
);
613 buf
.appendAscii( PyStr_AsString(reprString
.get()) );
614 buf
.appendAscii(" to a UNO type");
617 buf
.appendAscii("; caught exception: ");
618 buf
.append(*pWrapped
);
620 return buf
.makeStringAndClear();
623 Any
Runtime::pyObject2Any ( const PyRef
& source
, enum ConversionMode mode
) const
624 throw ( com::sun::star::uno::RuntimeException
)
626 if( ! impl
->cargo
->valid
)
628 throw RuntimeException("pyuno runtime must be initialized before calling any2PyObject" );
632 PyObject
*o
= source
.get();
637 // In Python 3, there is no PyInt type.
638 #if PY_MAJOR_VERSION < 3
639 else if (PyInt_Check (o
))
643 sal_Bool b
= sal_True
;
644 a
= Any( &b
, cppu::UnoType
<bool>::get() );
646 else if ( o
== Py_False
)
648 sal_Bool b
= sal_False
;
649 a
= Any( &b
, cppu::UnoType
<bool>::get() );
653 sal_Int32 l
= (sal_Int32
) PyLong_AsLong( o
);
654 if( l
< 128 && l
>= -128 )
656 sal_Int8 b
= (sal_Int8
) l
;
659 else if( l
<= 0x7fff && l
>= -0x8000 )
661 sal_Int16 s
= (sal_Int16
) l
;
670 #endif /* PY_MAJOR_VERSION < 3 */
671 else if (PyLong_Check (o
))
673 #if PY_MAJOR_VERSION >= 3
674 // Convert the Python 3 booleans that are actually of type PyLong.
677 sal_Bool b
= sal_True
;
678 a
= Any(&b
, cppu::UnoType
<bool>::get());
680 else if(o
== Py_False
)
682 sal_Bool b
= sal_False
;
683 a
= Any(&b
, cppu::UnoType
<bool>::get());
687 #endif /* PY_MAJOR_VERSION >= 3 */
688 sal_Int64 l
= (sal_Int64
)PyLong_AsLong (o
);
689 if( l
< 128 && l
>= -128 )
691 sal_Int8 b
= (sal_Int8
) l
;
694 else if( l
<= 0x7fff && l
>= -0x8000 )
696 sal_Int16 s
= (sal_Int16
) l
;
699 else if( l
<= SAL_CONST_INT64(0x7fffffff) &&
700 l
>= -SAL_CONST_INT64(0x80000000) )
702 sal_Int32 l32
= (sal_Int32
) l
;
709 #if PY_MAJOR_VERSION >= 3
713 else if (PyFloat_Check (o
))
715 double d
= PyFloat_AsDouble (o
);
718 else if (PyStrBytes_Check(o
) || PyUnicode_Check(o
))
720 a
<<= pyString2ustring(o
);
722 else if (PyTuple_Check (o
))
724 Sequence
<Any
> s (PyTuple_Size (o
));
725 for (int i
= 0; i
< PyTuple_Size (o
); i
++)
727 s
[i
] = pyObject2Any (PyTuple_GetItem (o
, i
), mode
);
734 // should be removed, in case ByteSequence gets derived from String
735 if( PyObject_IsInstance( o
, getByteSequenceClass( runtime
).get() ) )
737 PyRef
str(PyObject_GetAttrString( o
, "value" ),SAL_NO_ACQUIRE
);
738 Sequence
< sal_Int8
> seq
;
739 if( PyStrBytes_Check( str
.get() ) )
741 seq
= Sequence
<sal_Int8
> (
742 reinterpret_cast<sal_Int8
*>(PyStrBytes_AsString(str
.get())), PyStrBytes_Size(str
.get()));
747 if( PyObject_IsInstance( o
, getTypeClass( runtime
).get() ) )
749 Type t
= PyType2Type( o
);
752 else if( PyObject_IsInstance( o
, getEnumClass( runtime
).get() ) )
754 a
= PyEnum2Enum( o
);
756 else if( isInstanceOfStructOrException( o
) )
758 PyRef
struc(PyObject_GetAttrString( o
, "value" ),SAL_NO_ACQUIRE
);
759 PyUNO
* obj
= reinterpret_cast<PyUNO
*>(struc
.get());
760 Reference
< XMaterialHolder
> holder( obj
->members
->xInvocation
, UNO_QUERY
);
762 a
= holder
->getMaterial();
765 throw RuntimeException(
766 "struct or exception wrapper does not support XMaterialHolder" );
769 else if( PyObject_IsInstance( o
, getPyUnoClass().get() ) )
772 o_pi
= reinterpret_cast<PyUNO
*>(o
);
773 if (o_pi
->members
->wrappedObject
.getValueTypeClass () ==
774 com::sun::star::uno::TypeClass_STRUCT
||
775 o_pi
->members
->wrappedObject
.getValueTypeClass () ==
776 com::sun::star::uno::TypeClass_EXCEPTION
)
778 Reference
<XMaterialHolder
> my_mh (o_pi
->members
->xInvocation
, UNO_QUERY
);
782 throw RuntimeException(
783 "struct wrapper does not support XMaterialHolder" );
786 a
= my_mh
->getMaterial ();
790 a
= o_pi
->members
->wrappedObject
;
793 else if( PyObject_IsInstance( o
, getCharClass( runtime
).get() ) )
795 sal_Unicode c
= PyChar2Unicode( o
);
796 a
.setValue( &c
, cppu::UnoType
<cppu::UnoCharType
>::get());
798 else if( PyObject_IsInstance( o
, getAnyClass( runtime
).get() ) )
800 if( ACCEPT_UNO_ANY
== mode
)
802 a
= pyObject2Any( PyRef( PyObject_GetAttrString( o
, "value" ), SAL_NO_ACQUIRE
) );
804 pyObject2Any( PyRef( PyObject_GetAttrString( o
, "type" ), SAL_NO_ACQUIRE
) ) >>= t
;
808 a
= getImpl()->cargo
->xTypeConverter
->convertTo( a
, t
);
810 catch( const com::sun::star::uno::Exception
& e
)
812 throw WrappedTargetRuntimeException(
813 e
.Message
, e
.Context
, makeAny(e
));
818 throw RuntimeException(
819 "uno.Any instance not accepted during method call, "
820 "use uno.invoke instead" );
825 Reference
< XInterface
> mappedObject
;
826 Reference
< XInvocation
> adapterObject
;
828 // instance already mapped out to the world ?
829 PyRef2Adapter::iterator ii
= impl
->cargo
->mappedObjects
.find( PyRef( o
) );
830 if( ii
!= impl
->cargo
->mappedObjects
.end() )
832 adapterObject
= ii
->second
;
835 if( adapterObject
.is() )
837 // object got already bridged !
838 Reference
< com::sun::star::lang::XUnoTunnel
> tunnel( adapterObject
, UNO_QUERY
);
840 Adapter
*pAdapter
= reinterpret_cast<Adapter
*>(
841 tunnel
->getSomething(
842 ::pyuno::Adapter::getUnoTunnelImplementationId() ) );
844 mappedObject
= impl
->cargo
->xAdapterFactory
->createAdapter(
845 adapterObject
, pAdapter
->getWrappedTypes() );
850 Sequence
<Type
> interfaces
= invokeGetTypes(*this, o
);
851 if (interfaces
.getLength())
853 Adapter
*pAdapter
= new Adapter( o
, interfaces
);
855 getImpl()->cargo
->xAdapterFactory
->createAdapter(
856 pAdapter
, interfaces
);
858 // keep a list of exported objects to ensure object identity !
859 impl
->cargo
->mappedObjects
[ PyRef(o
) ] =
860 com::sun::star::uno::WeakReference
< XInvocation
> ( pAdapter
);
862 } catch (InvocationTargetException
const& e
) {
863 OUString
const msg(lcl_ExceptionMessage(o
, &e
.Message
));
864 throw WrappedTargetRuntimeException( // re-wrap that
865 msg
, e
.Context
, e
.TargetException
);
868 if( mappedObject
.is() )
870 a
= com::sun::star::uno::makeAny( mappedObject
);
874 OUString
const msg(lcl_ExceptionMessage(o
, 0));
875 throw RuntimeException(msg
);
882 Any
Runtime::extractUnoException( const PyRef
& excType
, const PyRef
&excValue
, const PyRef
&excTraceback
) const
886 if( excTraceback
.is() )
894 unoModule
= impl
->cargo
->getUnoModule();
896 catch (const Exception
&ei
)
903 PyRef
extractTraceback(
904 PyDict_GetItemString(unoModule
.get(),"_uno_extract_printable_stacktrace" ) );
906 if( PyCallable_Check(extractTraceback
.get()) )
908 PyRef
args( PyTuple_New( 1), SAL_NO_ACQUIRE
, NOT_NULL
);
909 PyTuple_SetItem( args
.get(), 0, excTraceback
.getAcquired() );
910 PyRef
pyStr( PyObject_CallObject( extractTraceback
.get(),args
.get() ), SAL_NO_ACQUIRE
);
911 str
= OUString::createFromAscii( PyStr_AsString(pyStr
.get()) );
915 str
= "Couldn't find uno._uno_extract_printable_stacktrace";
920 str
= "Could not load uno.py, no stacktrace available";
921 if ( !e
.Message
.isEmpty() )
923 str
+= OUString (" (Error loading uno.py: ");
925 str
+= OUString (")");
932 // it may occur, that no traceback is given (e.g. only native code below)
933 str
= "no traceback available";
936 if( isInstanceOfStructOrException( excValue
.get() ) )
938 ret
= pyObject2Any( excValue
);
943 PyRef
typeName( PyObject_Str( excType
.get() ), SAL_NO_ACQUIRE
);
946 buf
.appendAscii( PyStr_AsString( typeName
.get() ) );
950 buf
.appendAscii( "no typename available" );
952 buf
.appendAscii( ": " );
953 PyRef
valueRep( PyObject_Str( excValue
.get() ), SAL_NO_ACQUIRE
);
956 buf
.appendAscii( PyStr_AsString( valueRep
.get()));
960 buf
.appendAscii( "Couldn't convert exception value to a string" );
962 buf
.appendAscii( ", traceback follows\n" );
966 buf
.appendAscii( "\n" );
970 buf
.appendAscii( ", no traceback available\n" );
973 e
.Message
= buf
.makeStringAndClear();
974 #if OSL_DEBUG_LEVEL > 0
975 fprintf( stderr
, "Python exception: %s\n",
976 OUStringToOString(e
.Message
, RTL_TEXTENCODING_UTF8
).getStr() );
978 ret
= com::sun::star::uno::makeAny( e
);
984 PyThreadAttach::PyThreadAttach( PyInterpreterState
*interp
)
985 throw ( com::sun::star::uno::RuntimeException
)
987 tstate
= PyThreadState_New( interp
);
989 throw RuntimeException( "Couldn't create a pythreadstate" );
990 PyEval_AcquireThread( tstate
);
993 PyThreadAttach::~PyThreadAttach()
995 PyThreadState_Clear( tstate
);
996 PyEval_ReleaseThread( tstate
);
997 PyThreadState_Delete( tstate
);
1000 PyThreadDetach::PyThreadDetach() throw ( com::sun::star::uno::RuntimeException
)
1002 tstate
= PyThreadState_Get();
1003 PyEval_ReleaseThread( tstate
);
1006 /** Acquires the global interpreter lock again
1009 PyThreadDetach::~PyThreadDetach()
1011 PyEval_AcquireThread( tstate
);
1015 PyRef
RuntimeCargo::getUnoModule()
1017 if( ! dictUnoModule
.is() )
1019 dictUnoModule
= importUnoModule();
1021 return dictUnoModule
;
1025 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */