20#include <config_folders.h>
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>
33#include <typelib/typedescription.hxx>
35#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
36#include <com/sun/star/beans/XMaterialHolder.hpp>
37#include <com/sun/star/beans/theIntrospection.hpp>
38#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
39#include <com/sun/star/script/Converter.hpp>
40#include <com/sun/star/script/InvocationAdapterFactory.hpp>
41#include <com/sun/star/script/XInvocation2.hpp>
42#include <com/sun/star/reflection/theCoreReflection.hpp>
43#include <com/sun/star/lang/XSingleServiceFactory.hpp>
51using com::sun::star::uno::XInterface;
52using com::sun::star::uno::Any;
53using com::sun::star::uno::TypeDescription;
55using com::sun::star::uno::Type;
56using com::sun::star::uno::UNO_QUERY;
57using com::sun::star::uno::Exception;
58using com::sun::star::uno::RuntimeException;
59using com::sun::star::uno::XComponentContext;
60using com::sun::star::lang::WrappedTargetRuntimeException;
61using com::sun::star::lang::XSingleServiceFactory;
62using com::sun::star::lang::XUnoTunnel;
63using com::sun::star::reflection::theCoreReflection;
64using com::sun::star::reflection::InvocationTargetException;
65using com::sun::star::script::Converter;
66using com::sun::star::script::XTypeConverter;
67using com::sun::star::script::XInvocation;
68using com::sun::star::beans::XMaterialHolder;
69using com::sun::star::beans::theIntrospection;
76 PyVarObject_HEAD_INIT (&PyType_Type, 0)
81#
if PY_VERSION_HEX >= 0x03080000
127#
if PY_VERSION_HEX >= 0x03040000
129#
if PY_VERSION_HEX >= 0x03080000
131#
if PY_VERSION_HEX < 0x03090000
133#pragma clang diagnostic push
134#pragma clang diagnostic ignored
"-Wdeprecated-declarations"
138#pragma clang diagnostic pop
151 PyThreadState * state = PyThreadState_Get();
154 throw RuntimeException(
"python global interpreter must be held (thread must be attached)" );
157 PyObject* pModule = PyImport_AddModule(
"__main__");
164 globalDict =
PyRef( PyModule_GetDict(pModule));
166 if( ! globalDict.
is() )
170 runtimeImpl = PyDict_GetItemString( globalDict.
get() ,
"pyuno_runtime" );
178 if( PyErr_Occurred() )
180 PyRef excType, excValue, excTraceback;
181 PyErr_Fetch(
reinterpret_cast<PyObject **
>(&excType),
reinterpret_cast<PyObject**
>(&excValue),
reinterpret_cast<PyObject**
>(&excTraceback));
185 PyRef str( PyObject_Str( excTraceback.
get() ), SAL_NO_ACQUIRE );
188 buf.append(
"python object raised an unknown exception (" );
189 PyRef valueRep( PyObject_Repr( excValue.
get() ), SAL_NO_ACQUIRE );
190 buf.appendAscii( PyUnicode_AsUTF8( valueRep.
get())).append(
", traceback follows\n" );
191 buf.appendAscii( PyUnicode_AsUTF8( str.
get() ) );
204 osl_getModuleURLFromFunctionAddress(
207 fileName = fileName.copy( fileName.lastIndexOf(
'/' )+1 );
209 fileName +=
"../" LIBO_ETC_FOLDER
"/";
212 rtl::Bootstrap bootstrapHandle( fileName );
215 if( bootstrapHandle.getFrom(
"PYUNO_LOGLEVEL", str ) )
219 else if ( str ==
"CALL" )
221 else if ( str ==
"ARGS" )
225 fprintf( stderr,
"unknown loglevel %s\n",
233 if( !bootstrapHandle.getFrom(
"PYUNO_LOGTARGET", str ) )
236 if ( str ==
"stdout" )
238 else if ( str ==
"stderr" )
243 data.Size =
sizeof( data );
245 nullptr , osl_Process_IDENTIFIER , &data );
246 osl_getSystemPathFromFileURL( str.pData, &str.pData);
249 o += OString::number( data.Ident );
251 *ppFile = fopen( o.getStr() ,
"w" );
255 setvbuf( *ppFile,
nullptr, _IONBF, 0 );
259 fprintf( stderr,
"couldn't create file %s\n",
284 ctx->getServiceManager()->createInstanceWithContext(
285 "com.sun.star.script.Invocation",
287 css::uno::UNO_QUERY_THROW );
291 throw RuntimeException(
"pyuno: couldn't instantiate typeconverter service" );
299 Any a =
ctx->getValueByName(
"/singletons/com.sun.star.reflection.theTypeDescriptionManager");
302 throw RuntimeException(
"pyuno: couldn't retrieve typedescriptionmanager" );
305 return PyRef(
reinterpret_cast< PyObject *
> ( me ), SAL_NO_ACQUIRE );
320 PyRef globalDict, runtime;
324 if( runtime.
is() &&
impl->cargo->valid )
326 throw RuntimeException(
"pyuno runtime has already been initialized before" );
329 PyDict_SetItemString( globalDict.
get(),
"pyuno_runtime" , keep.
get() );
330 Py_XINCREF( keep.
get() );
336 PyRef globalDict, runtime;
339 return runtime.
is() &&
impl->cargo->valid;
345 PyRef globalDict, runtime;
350 "pyuno runtime is not initialized, "
351 "(the pyuno.bootstrap needs to be called before using any uno classes)" );
354 Py_XINCREF( runtime.
get() );
360 Py_XINCREF(
reinterpret_cast< PyObject *
>(
impl) );
365 Py_XDECREF(
reinterpret_cast< PyObject *
>(
impl) );
370 PyRef temp(
reinterpret_cast< PyObject *
>(r.
impl) );
371 Py_XINCREF( temp.
get() );
372 Py_XDECREF(
reinterpret_cast< PyObject *
>(
impl) );
379 if( !
impl->cargo->valid )
381 throw RuntimeException(
"pyuno runtime must be initialized before calling any2PyObject" );
384 switch (
a.getValueTypeClass ())
386 case css::uno::TypeClass_VOID:
389 return PyRef(Py_None);
391 case css::uno::TypeClass_CHAR:
396 case css::uno::TypeClass_BOOLEAN:
404 case css::uno::TypeClass_BYTE:
405 case css::uno::TypeClass_SHORT:
406 case css::uno::TypeClass_UNSIGNED_SHORT:
407 case css::uno::TypeClass_LONG:
411 return PyRef( PyLong_FromLong (l), SAL_NO_ACQUIRE );
413 case css::uno::TypeClass_UNSIGNED_LONG:
417 return PyRef( PyLong_FromUnsignedLong (l), SAL_NO_ACQUIRE );
419 case css::uno::TypeClass_HYPER:
423 return PyRef( PyLong_FromLongLong (l), SAL_NO_ACQUIRE);
425 case css::uno::TypeClass_UNSIGNED_HYPER:
429 return PyRef( PyLong_FromUnsignedLongLong (l), SAL_NO_ACQUIRE);
431 case css::uno::TypeClass_FLOAT:
435 return PyRef(PyFloat_FromDouble (f), SAL_NO_ACQUIRE);
437 case css::uno::TypeClass_DOUBLE:
441 return PyRef( PyFloat_FromDouble (
d), SAL_NO_ACQUIRE);
443 case css::uno::TypeClass_STRING:
449 case css::uno::TypeClass_TYPE:
456 o.getStr(),
t.getTypeClass(), *
this),
459 case css::uno::TypeClass_ANY:
465 case css::uno::TypeClass_ENUM:
467 sal_Int32 l = *
static_cast<sal_Int32
const *
>(
a.getValue());
468 TypeDescription desc(
a.getValueType() );
472 typelib_EnumTypeDescription *pEnumDesc =
473 reinterpret_cast<typelib_EnumTypeDescription *
>(desc.get());
474 for(
int i = 0 ;
i < pEnumDesc->nEnumValues ;
i ++ )
476 if( pEnumDesc->pEnumValues[
i] == l )
478 OString
v =
OUStringToOString( OUString::unacquired(&pEnumDesc->ppEnumNames[
i]), RTL_TEXTENCODING_ASCII_US);
479 OString e =
OUStringToOString( OUString::unacquired(&pEnumDesc->aBase.pTypeName), RTL_TEXTENCODING_ASCII_US);
485 " with invalid value " + OUString::number(l) );
487 case css::uno::TypeClass_EXCEPTION:
488 case css::uno::TypeClass_STRUCT:
490 PyRef excClass =
getClass(
a.getValueType().getTypeName(), *
this );
492 PyRef argsTuple( PyTuple_New( 1 ) , SAL_NO_ACQUIRE,
NOT_NULL );
493 PyTuple_SetItem( argsTuple.
get() , 0 ,
value.getAcquired() );
494 PyRef ret( PyObject_CallObject( excClass.
get() , argsTuple.
get() ), SAL_NO_ACQUIRE );
497 throw RuntimeException(
"Couldn't instantiate python representation of structured UNO type " +
498 a.getValueType().getTypeName() );
501 if(
auto e = o3tl::tryAccess<css::uno::Exception>(
a) )
510 PyObject_SetAttrString( ret.
get(),
"args",
args.get() );
514 case css::uno::TypeClass_SEQUENCE:
519 if(
a >>= byteSequence )
529 PyRef tuple( PyTuple_New (s.getLength()), SAL_NO_ACQUIRE,
NOT_NULL);
533 for (
i = 0;
i < s.getLength ();
i++)
536 OSL_ASSERT( element.
is() );
540 catch( css::uno::Exception & )
542 for( ;
i < s.getLength() ;
i ++ )
544 Py_INCREF( Py_None );
545 PyTuple_SetItem( tuple.
get(),
i, Py_None );
552 case css::uno::TypeClass_INTERFACE:
556 if (!tmp_interface.is ())
563 throw RuntimeException(
"Unknown UNO type class " + OUString::number(
static_cast<int>(
a.getValueTypeClass())) );
572 PyRef method( PyObject_GetAttrString( o ,
"getTypes" ), SAL_NO_ACQUIRE );
574 if( method.
is() && PyCallable_Check( method.
get() ) )
576 PyRef types( PyObject_CallObject( method.
get(),
nullptr ) , SAL_NO_ACQUIRE );
578 if( types.
is() && PyTuple_Check( types.
get() ) )
580 int size = PyTuple_Size( types.
get() );
583 ret.realloc(
size + 1 );
584 auto pret = ret.getArray();
585 for(
int i = 0 ;
i <
size ;
i ++ )
600 buf.append(
"Couldn't convert ");
601 PyRef reprString( PyObject_Str(o), SAL_NO_ACQUIRE );
602 buf.appendAscii( PyUnicode_AsUTF8(reprString.
get()) );
603 buf.append(
" to a UNO type");
606 buf.append(
"; caught exception: ");
607 buf.append(*pWrapped);
609 return buf.makeStringAndClear();
616 if( !PyIter_Check( pObj ))
619 PyObject *pItem = PyIter_Next( pObj );
622 if( PyErr_Occurred() )
630 ::std::vector<Any> items;
633 PyRef rItem( pItem, SAL_NO_ACQUIRE );
635 pItem = PyIter_Next( pObj );
646 throw RuntimeException(
"pyuno runtime must be initialized before calling any2PyObject" );
650 PyObject *o = source.
get();
655 else if (PyLong_Check (o))
662 else if(o == Py_False)
668 sal_Int64 l =
static_cast<sal_Int64
>(PyLong_AsLong (o));
669 if( l < 128 && l >= -128 )
674 else if( l <= 0x7fff && l >= -0x8000 )
676 sal_Int16 s =
static_cast<sal_Int16
>(l);
679 else if( l <= SAL_CONST_INT64(0x7fffffff) &&
680 l >= -SAL_CONST_INT64(0x80000000) )
682 sal_Int32 l32 =
static_cast<sal_Int32
>(l);
691 else if (PyFloat_Check (o))
693 double d = PyFloat_AsDouble (o);
696 else if (PyBytes_Check(o) || PyUnicode_Check(o))
700 else if (PyTuple_Check (o))
703 auto sRange = asNonConstRange(s);
704 for (Py_ssize_t
i = 0;
i < PyTuple_Size (o);
i++)
710 else if (PyList_Check (o))
712 Py_ssize_t l = PyList_Size (o);
714 auto sRange = asNonConstRange(s);
715 for (Py_ssize_t
i = 0;
i < l;
i++)
727 PyRef str(PyObject_GetAttrString( o ,
"value" ),SAL_NO_ACQUIRE);
729 if( PyBytes_Check( str.
get() ) )
732 reinterpret_cast<sal_Int8*
>(PyBytes_AsString(str.
get())), PyBytes_Size(str.
get()));
748 PyRef struc(PyObject_GetAttrString( o ,
"value" ),SAL_NO_ACQUIRE);
754 "struct or exception wrapper does not support XMaterialHolder" );
757 a = holder->getMaterial();
769 a = my_mh->getMaterial();
780 "uno.Any instance not accepted during method call, "
781 "use uno.invoke instead" );
792 catch(
const css::uno::Exception & e )
795 throw WrappedTargetRuntimeException(
796 e.Message, e.Context, anyEx);
806 PyRef2Adapter::iterator ii =
impl->cargo->mappedObjects.find(
PyRef( o ) );
807 if( ii !=
impl->cargo->mappedObjects.end() )
809 adapterObject = ii->second;
812 if( adapterObject.is() )
815 auto pAdapter = comphelper::getFromUnoTunnel<Adapter>(adapterObject);
817 mappedObject =
impl->cargo->xAdapterFactory->createAdapter(
818 adapterObject, pAdapter->getWrappedTypes() );
824 if (interfaces.getLength())
829 pAdapter, interfaces );
833 css::uno::WeakReference< XInvocation > ( pAdapter );
835 }
catch (InvocationTargetException
const& e) {
837 throw WrappedTargetRuntimeException(
838 msg, e.Context, e.TargetException);
841 if( mappedObject.is() )
859 if( excTraceback.
is() )
867 unoModule =
impl->cargo->getUnoModule();
876 PyRef extractTraceback(
877 PyDict_GetItemString(unoModule.
get(),
"_uno_extract_printable_stacktrace" ) );
879 if( PyCallable_Check(extractTraceback.
get()) )
883 PyRef pyStr( PyObject_CallObject( extractTraceback.
get(),
args.get() ), SAL_NO_ACQUIRE);
884 str = OUString::fromUtf8(PyUnicode_AsUTF8(pyStr.
get()));
888 str =
"Couldn't find uno._uno_extract_printable_stacktrace";
893 str =
"Could not load uno.py, no stacktrace available";
894 if ( !e.Message.isEmpty() )
896 str +=
" (Error loading uno.py: " + e.Message +
")";
904 str =
"no traceback available";
917 buf.appendAscii( PyUnicode_AsUTF8(
typeName.get() ) );
921 buf.append(
"no typename available" );
924 PyRef valueRep( PyObject_Str( excValue.
get() ), SAL_NO_ACQUIRE );
927 buf.appendAscii( PyUnicode_AsUTF8( valueRep.
get()));
931 buf.append(
"Couldn't convert exception value to a string" );
933 buf.append(
", traceback follows\n" );
941 buf.append(
", no traceback available\n" );
944 e.Message = buf.makeStringAndClear();
945#if OSL_DEBUG_LEVEL > 0
946 fprintf( stderr,
"Python exception: %s\n",
956 : m_isNewState(false)
960 tstate = PyGILState_GetThisThreadState();
964 tstate = PyThreadState_New( interp );
968 PyEval_AcquireThread(
tstate);
975 PyThreadState_Clear(
tstate );
978 PyThreadState_DeleteCurrent();
982 PyEval_ReleaseThread(
tstate );
988 tstate = PyThreadState_Get();
989 PyEval_ReleaseThread(
tstate );
998 PyEval_AcquireThread(
tstate );
css::uno::Type const & get()
Helper class for keeping references to python objects.
bool is() const
returns 1 when the reference points to a python object python object, otherwise 0.
PyObject * get() const noexcept
PyObject * getAcquired() const
~PyThreadAttach()
Releases the global interpreter lock and destroys the thread state.
PyThreadAttach(const PyThreadAttach &)=delete
~PyThreadDetach()
Acquires the global interpreter lock again.
PyThreadDetach()
Releases the global interpreter lock.
The pyuno::Runtime class keeps the internal state of the python UNO bridge for the currently in use p...
static bool isInitialized()
Checks, whether the uno runtime is already initialized in the current python interpreter.
css::uno::Any extractUnoException(const PyRef &excType, const PyRef &excValue, const PyRef &excTraceback) const
extracts a proper uno exception from a given python exception
css::uno::Any pyObject2Any(const PyRef &source, enum ConversionMode mode=REJECT_UNO_ANY) const
converts a Python object to a UNO any
PyRef any2PyObject(const css::uno::Any &source) const
converts something contained in a UNO Any to a Python object
Runtime & operator=(const Runtime &)
RuntimeImpl * getImpl() const
Returns the internal handle.
Runtime()
preconditions: python has been initialized before, the global interpreter lock is held and pyuno has ...
static void initialize(const css::uno::Reference< css::uno::XComponentContext > &ctx)
Initializes the python-UNO bridge.
bool pyIterUnpack(PyObject *const, css::uno::Any &) const
Safely unpacks a Python iterator into a sequence, then stores it in an Any.
#define SAL_CONFIGFILE(name)
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
Any SAL_CALL getCaughtException()
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
struct stRuntimeImpl RuntimeImpl
void log(RuntimeCargo *cargo, sal_Int32 level, std::u16string_view logString)
void raiseInvocationTargetExceptionWhenNeeded(const Runtime &runtime)
PyObject * PyUNO_Type_new(const char *typeName, css::uno::TypeClass t, const Runtime &r)
bool isInstanceOfStructOrException(PyObject *obj)
PyRef PyUNO_new(const Any &targetInterface, const Reference< XSingleServiceFactory > &ssf)
static OUString lcl_ExceptionMessage(PyObject *const o, OUString const *const pWrapped)
PyRef getCharClass(const Runtime &)
PyRef getPyUnoStructClass()
PyObject * PyUNO_ByteSequence_new(const css::uno::Sequence< sal_Int8 > &, const Runtime &r)
PyObject * PyUNO_char_new(sal_Unicode c, const Runtime &r)
static PyTypeObject RuntimeImpl_Type
PyRef ustring2PyString(std::u16string_view source)
sal_Unicode PyChar2Unicode(PyObject *o)
PyObject * PyUNO_Enum_new(const char *enumBase, const char *enumValue, const Runtime &r)
PyRef getTypeClass(const Runtime &)
PyRef getEnumClass(const Runtime &)
static void getRuntimeImpl(PyRef &globalDict, PyRef &runtimeImpl)
css::uno::Type PyType2Type(PyObject *o)
PyRef getByteSequenceClass(const Runtime &)
OUString pyString2ustring(PyObject *str)
static void readLoggingConfig(sal_Int32 *pLevel, FILE **ppFile)
@ NOT_NULL
definition of a no acquire enum for ctors
PyRef ustring2PyUnicode(const OUString &source)
PyRef getClass(const OUString &name, const Runtime &runtime)
css::uno::Any PyEnum2Enum(PyObject *obj)
static Sequence< Type > invokeGetTypes(const Runtime &r, PyObject *o)
PyRef getAnyClass(const Runtime &)
PyRef PyUNOStruct_new(const css::uno::Any &targetInterface, const css::uno::Reference< css::lang::XSingleServiceFactory > &ssf)
static PyRef importUnoModule()
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
css::uno::Any wrappedObject
css::uno::Reference< css::script::XInvocation2 > xInvocation
PyObject_HEAD PyUNOInternals * members
css::uno::Reference< css::script::XTypeConverter > xTypeConverter
css::uno::Reference< css::reflection::XIdlReflection > xCoreReflection
css::uno::Reference< css::lang::XSingleServiceFactory > xInvocation
css::uno::Reference< css::container::XHierarchicalNameAccess > xTdMgr
PyRef const & getUnoModule()
css::uno::Reference< css::beans::XIntrospection > xIntrospection
css::uno::Reference< css::script::XInvocationAdapterFactory2 > xAdapterFactory
css::uno::Reference< css::uno::XComponentContext > xContext
static PyRef create(const css::uno::Reference< css::uno::XComponentContext > &xContext)
PyObject_HEAD struct RuntimeCargo * cargo
static void del(PyObject *self)