LibreOffice Module pyuno (master) 1
pyuno_runtime.cxx
Go to the documentation of this file.
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.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <config_folders.h>
21
22#include "pyuno_impl.hxx"
23
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>
31#include <rtl/ref.hxx>
32
33#include <typelib/typedescription.hxx>
34
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>
47
48#include <vector>
49
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;
70
71namespace pyuno
72{
73
74static PyTypeObject RuntimeImpl_Type =
75{
76 PyVarObject_HEAD_INIT (&PyType_Type, 0)
77 "pyuno_runtime",
78 sizeof (RuntimeImpl),
79 0,
81#if PY_VERSION_HEX >= 0x03080000
82 0, // Py_ssize_t tp_vectorcall_offset
83#else
84 nullptr, // printfunc tp_print
85#endif
86 nullptr,
87 nullptr,
88 nullptr,
89 nullptr,
90 nullptr,
91 nullptr,
92 nullptr,
93 nullptr,
94 nullptr,
95 nullptr,
96 nullptr,
97 nullptr,
98 nullptr,
99 0,
100 nullptr,
101 nullptr,
102 nullptr,
103 nullptr,
104 0,
105 nullptr,
106 nullptr,
107 nullptr,
108 nullptr,
109 nullptr,
110 nullptr,
111 nullptr,
112 nullptr,
113 nullptr,
114 0,
115 nullptr,
116 nullptr,
117 nullptr,
118 nullptr,
119 nullptr,
120 nullptr,
121 nullptr,
122 nullptr,
123 nullptr,
124 nullptr,
125 nullptr
126 , 0
127#if PY_VERSION_HEX >= 0x03040000
128 , nullptr
129#if PY_VERSION_HEX >= 0x03080000
130 , nullptr // vectorcallfunc tp_vectorcall
131#if PY_VERSION_HEX < 0x03090000
132#if defined __clang__
133#pragma clang diagnostic push
134#pragma clang diagnostic ignored "-Wdeprecated-declarations"
135#endif
136 , nullptr // tp_print
137#if defined __clang__
138#pragma clang diagnostic pop
139#endif
140#endif
141#endif
142#endif
143};
144
145/*----------------------------------------------------------------------
146 Runtime implementation
147 -----------------------------------------------------------------------*/
149static void getRuntimeImpl( PyRef & globalDict, PyRef &runtimeImpl )
150{
151 PyThreadState * state = PyThreadState_Get();
152 if( ! state )
153 {
154 throw RuntimeException( "python global interpreter must be held (thread must be attached)" );
155 }
156
157 PyObject* pModule = PyImport_AddModule("__main__");
158
159 if (!pModule)
160 {
161 throw RuntimeException("can't import __main__ module");
162 }
163
164 globalDict = PyRef( PyModule_GetDict(pModule));
165
166 if( ! globalDict.is() ) // FATAL !
167 {
168 throw RuntimeException("can't find __main__ module");
169 }
170 runtimeImpl = PyDict_GetItemString( globalDict.get() , "pyuno_runtime" );
171}
172
175{
176 // import the uno module
177 PyRef module( PyImport_ImportModule( "uno" ), SAL_NO_ACQUIRE, NOT_NULL );
178 if( PyErr_Occurred() )
179 {
180 PyRef excType, excValue, excTraceback;
181 PyErr_Fetch( reinterpret_cast<PyObject **>(&excType), reinterpret_cast<PyObject**>(&excValue), reinterpret_cast<PyObject**>(&excTraceback));
182 // As of Python 2.7 this gives a rather non-useful "<traceback object at 0xADDRESS>",
183 // but it is the best we can do in the absence of uno._uno_extract_printable_stacktrace
184 // Who knows, a future Python might print something better.
185 PyRef str( PyObject_Str( excTraceback.get() ), SAL_NO_ACQUIRE );
186
187 OUStringBuffer buf;
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() ) );
192 buf.append( ")" );
193 throw RuntimeException( buf.makeStringAndClear() );
194 }
195 PyRef dict( PyModule_GetDict( module.get() ) );
196 return dict;
197}
198
199static void readLoggingConfig( sal_Int32 *pLevel, FILE **ppFile )
200{
201 *pLevel = LogLevel::NONE;
202 *ppFile = nullptr;
203 OUString fileName;
204 osl_getModuleURLFromFunctionAddress(
205 reinterpret_cast< oslGenericFunction >(readLoggingConfig),
206 &fileName.pData );
207 fileName = fileName.copy( fileName.lastIndexOf( '/' )+1 );
208#ifdef MACOSX
209 fileName += "../" LIBO_ETC_FOLDER "/";
210#endif
211 fileName += SAL_CONFIGFILE("pyuno" );
212 rtl::Bootstrap bootstrapHandle( fileName );
213
214 OUString str;
215 if( bootstrapHandle.getFrom( "PYUNO_LOGLEVEL", str ) )
216 {
217 if ( str == "NONE" )
218 *pLevel = LogLevel::NONE;
219 else if ( str == "CALL" )
220 *pLevel = LogLevel::CALL;
221 else if ( str == "ARGS" )
222 *pLevel = LogLevel::ARGS;
223 else
224 {
225 fprintf( stderr, "unknown loglevel %s\n",
226 OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
227 }
228 }
229 if( *pLevel <= LogLevel::NONE )
230 return;
231
232 *ppFile = stdout;
233 if( !bootstrapHandle.getFrom( "PYUNO_LOGTARGET", str ) )
234 return;
235
236 if ( str == "stdout" )
237 *ppFile = stdout;
238 else if ( str == "stderr" )
239 *ppFile = stderr;
240 else
241 {
242 oslProcessInfo data;
243 data.Size = sizeof( data );
244 osl_getProcessInfo(
245 nullptr , osl_Process_IDENTIFIER , &data );
246 osl_getSystemPathFromFileURL( str.pData, &str.pData);
247 OString o = OUStringToOString( str, osl_getThreadTextEncoding() );
248 o += ".";
249 o += OString::number( data.Ident );
250
251 *ppFile = fopen( o.getStr() , "w" );
252 if ( *ppFile )
253 {
254 // do not buffer (useful if e.g. analyzing a crash)
255 setvbuf( *ppFile, nullptr, _IONBF, 0 );
256 }
257 else
258 {
259 fprintf( stderr, "couldn't create file %s\n",
260 OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
261
262 }
263 }
264}
265
266/*-------------------------------------------------------------------
267 RuntimeImpl implementations
268 *-------------------------------------------------------------------*/
270{
271 RuntimeImpl *me = PyObject_New (RuntimeImpl, &RuntimeImpl_Type);
272 if( ! me )
273 throw RuntimeException( "cannot instantiate pyuno::RuntimeImpl" );
274 me->cargo = nullptr;
275 // must use a different struct here, as the PyObject_New
276 // makes C++ unusable
277 RuntimeCargo *c = new RuntimeCargo;
278 readLoggingConfig( &(c->logLevel) , &(c->logFile) );
279 log( c, LogLevel::CALL, "Instantiating pyuno bridge" );
280
281 c->valid = true;
282 c->xContext = ctx;
284 ctx->getServiceManager()->createInstanceWithContext(
285 "com.sun.star.script.Invocation",
286 ctx ),
287 css::uno::UNO_QUERY_THROW );
288
289 c->xTypeConverter = Converter::create(ctx);
290 if( ! c->xTypeConverter.is() )
291 throw RuntimeException( "pyuno: couldn't instantiate typeconverter service" );
292
293 c->xCoreReflection = theCoreReflection::get(ctx);
294
295 c->xAdapterFactory = css::script::InvocationAdapterFactory::create(ctx);
296
297 c->xIntrospection = theIntrospection::get(ctx);
298
299 Any a = ctx->getValueByName("/singletons/com.sun.star.reflection.theTypeDescriptionManager");
300 a >>= c->xTdMgr;
301 if( ! c->xTdMgr.is() )
302 throw RuntimeException( "pyuno: couldn't retrieve typedescriptionmanager" );
303
304 me->cargo =c;
305 return PyRef( reinterpret_cast< PyObject * > ( me ), SAL_NO_ACQUIRE );
306}
307
308void stRuntimeImpl::del(PyObject* self)
309{
310 RuntimeImpl *me = reinterpret_cast< RuntimeImpl * > ( self );
311 if( me->cargo->logFile )
312 fclose( me->cargo->logFile );
313 delete me->cargo;
314 PyObject_Del (self);
315}
316
317
319{
320 PyRef globalDict, runtime;
321 getRuntimeImpl( globalDict , runtime );
322 RuntimeImpl *impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
323
324 if( runtime.is() && impl->cargo->valid )
325 {
326 throw RuntimeException("pyuno runtime has already been initialized before" );
327 }
328 PyRef keep( RuntimeImpl::create( ctx ) );
329 PyDict_SetItemString( globalDict.get(), "pyuno_runtime" , keep.get() );
330 Py_XINCREF( keep.get() );
331}
332
333
335{
336 PyRef globalDict, runtime;
337 getRuntimeImpl( globalDict , runtime );
338 RuntimeImpl *impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
339 return runtime.is() && impl->cargo->valid;
340}
341
343 : impl( nullptr )
344{
345 PyRef globalDict, runtime;
346 getRuntimeImpl( globalDict , runtime );
347 if( ! runtime.is() )
348 {
349 throw RuntimeException(
350 "pyuno runtime is not initialized, "
351 "(the pyuno.bootstrap needs to be called before using any uno classes)" );
352 }
353 impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
354 Py_XINCREF( runtime.get() );
355}
356
358{
359 impl = r.impl;
360 Py_XINCREF( reinterpret_cast< PyObject * >(impl) );
361}
362
364{
365 Py_XDECREF( reinterpret_cast< PyObject * >(impl) );
366}
367
369{
370 PyRef temp( reinterpret_cast< PyObject * >(r.impl) );
371 Py_XINCREF( temp.get() );
372 Py_XDECREF( reinterpret_cast< PyObject * >(impl) );
373 impl = r.impl;
374 return *this;
375}
376
377PyRef Runtime::any2PyObject (const Any &a ) const
378{
379 if( ! impl->cargo->valid )
380 {
381 throw RuntimeException("pyuno runtime must be initialized before calling any2PyObject" );
382 }
383
384 switch (a.getValueTypeClass ())
385 {
386 case css::uno::TypeClass_VOID:
387 {
388 Py_INCREF (Py_None);
389 return PyRef(Py_None);
390 }
391 case css::uno::TypeClass_CHAR:
392 {
393 sal_Unicode c = *o3tl::forceAccess<sal_Unicode>(a);
394 return PyRef( PyUNO_char_new( c , *this ), SAL_NO_ACQUIRE );
395 }
396 case css::uno::TypeClass_BOOLEAN:
397 {
398 bool b;
399 if ((a >>= b) && b)
400 return Py_True;
401 else
402 return Py_False;
403 }
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:
408 {
409 sal_Int32 l = 0;
410 a >>= l;
411 return PyRef( PyLong_FromLong (l), SAL_NO_ACQUIRE );
412 }
413 case css::uno::TypeClass_UNSIGNED_LONG:
414 {
415 sal_uInt32 l = 0;
416 a >>= l;
417 return PyRef( PyLong_FromUnsignedLong (l), SAL_NO_ACQUIRE );
418 }
419 case css::uno::TypeClass_HYPER:
420 {
421 sal_Int64 l = 0;
422 a >>= l;
423 return PyRef( PyLong_FromLongLong (l), SAL_NO_ACQUIRE);
424 }
425 case css::uno::TypeClass_UNSIGNED_HYPER:
426 {
427 sal_uInt64 l = 0;
428 a >>= l;
429 return PyRef( PyLong_FromUnsignedLongLong (l), SAL_NO_ACQUIRE);
430 }
431 case css::uno::TypeClass_FLOAT:
432 {
433 float f = 0.0;
434 a >>= f;
435 return PyRef(PyFloat_FromDouble (f), SAL_NO_ACQUIRE);
436 }
437 case css::uno::TypeClass_DOUBLE:
438 {
439 double d = 0.0;
440 a >>= d;
441 return PyRef( PyFloat_FromDouble (d), SAL_NO_ACQUIRE);
442 }
443 case css::uno::TypeClass_STRING:
444 {
445 OUString tmp_ostr;
446 a >>= tmp_ostr;
447 return ustring2PyUnicode( tmp_ostr );
448 }
449 case css::uno::TypeClass_TYPE:
450 {
451 Type t;
452 a >>= t;
453 OString o = OUStringToOString( t.getTypeName(), RTL_TEXTENCODING_ASCII_US );
454 return PyRef(
456 o.getStr(), t.getTypeClass(), *this),
457 SAL_NO_ACQUIRE);
458 }
459 case css::uno::TypeClass_ANY:
460 {
461 //I don't think this can happen.
462 Py_INCREF (Py_None);
463 return Py_None;
464 }
465 case css::uno::TypeClass_ENUM:
466 {
467 sal_Int32 l = *static_cast<sal_Int32 const *>(a.getValue());
468 TypeDescription desc( a.getValueType() );
469 if( desc.is() )
470 {
471 desc.makeComplete();
472 typelib_EnumTypeDescription *pEnumDesc =
473 reinterpret_cast<typelib_EnumTypeDescription *>(desc.get());
474 for( int i = 0 ; i < pEnumDesc->nEnumValues ; i ++ )
475 {
476 if( pEnumDesc->pEnumValues[i] == l )
477 {
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);
480 return PyRef( PyUNO_Enum_new(e.getStr(),v.getStr(), *this ), SAL_NO_ACQUIRE );
481 }
482 }
483 }
484 throw RuntimeException( "Any carries enum " + a.getValueType().getTypeName() +
485 " with invalid value " + OUString::number(l) );
486 }
487 case css::uno::TypeClass_EXCEPTION:
488 case css::uno::TypeClass_STRUCT:
489 {
490 PyRef excClass = getClass( a.getValueType().getTypeName(), *this );
491 PyRef value = PyUNOStruct_new( a, getImpl()->cargo->xInvocation );
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 );
495 if( ! ret.is() )
496 {
497 throw RuntimeException( "Couldn't instantiate python representation of structured UNO type " +
498 a.getValueType().getTypeName() );
499 }
500
501 if( auto e = o3tl::tryAccess<css::uno::Exception>(a) )
502 {
503 // add the message in a standard python way !
504 PyRef args( PyTuple_New( 1 ), SAL_NO_ACQUIRE, NOT_NULL );
505
506 PyRef pymsg = ustring2PyString( e->Message );
507 PyTuple_SetItem( args.get(), 0 , pymsg.getAcquired() );
508 // the exception base functions want to have an "args" tuple,
509 // which contains the message
510 PyObject_SetAttrString( ret.get(), "args", args.get() );
511 }
512 return ret;
513 }
514 case css::uno::TypeClass_SEQUENCE:
515 {
517
518 Sequence< sal_Int8 > byteSequence;
519 if( a >>= byteSequence )
520 {
521 // byte sequence is treated in a special way because of performance reasons
522 // @since 0.9.2
523 return PyRef( PyUNO_ByteSequence_new( byteSequence, *this ), SAL_NO_ACQUIRE );
524 }
525 else
526 {
528 tc->convertTo (a, cppu::UnoType<decltype(s)>::get()) >>= s;
529 PyRef tuple( PyTuple_New (s.getLength()), SAL_NO_ACQUIRE, NOT_NULL);
530 int i=0;
531 try
532 {
533 for ( i = 0; i < s.getLength (); i++)
534 {
535 PyRef element = any2PyObject (tc->convertTo (s[i], s[i].getValueType() ));
536 OSL_ASSERT( element.is() );
537 PyTuple_SetItem( tuple.get(), i, element.getAcquired() );
538 }
539 }
540 catch( css::uno::Exception & )
541 {
542 for( ; i < s.getLength() ; i ++ )
543 {
544 Py_INCREF( Py_None );
545 PyTuple_SetItem( tuple.get(), i, Py_None );
546 }
547 throw;
548 }
549 return tuple;
550 }
551 }
552 case css::uno::TypeClass_INTERFACE:
553 {
554 Reference<XInterface> tmp_interface;
555 a >>= tmp_interface;
556 if (!tmp_interface.is ())
557 return Py_None;
558
559 return PyUNO_new( a, getImpl()->cargo->xInvocation );
560 }
561 default:
562 {
563 throw RuntimeException( "Unknown UNO type class " + OUString::number(static_cast<int>(a.getValueTypeClass())) );
564 }
565 }
566}
567
568static Sequence< Type > invokeGetTypes( const Runtime & r , PyObject * o )
569{
571
572 PyRef method( PyObject_GetAttrString( o , "getTypes" ), SAL_NO_ACQUIRE );
574 if( method.is() && PyCallable_Check( method.get() ) )
575 {
576 PyRef types( PyObject_CallObject( method.get(), nullptr ) , SAL_NO_ACQUIRE );
578 if( types.is() && PyTuple_Check( types.get() ) )
579 {
580 int size = PyTuple_Size( types.get() );
581
582 // add the XUnoTunnel interface for uno object identity concept (hack)
583 ret.realloc( size + 1 );
584 auto pret = ret.getArray();
585 for( int i = 0 ; i < size ; i ++ )
586 {
587 Any a = r.pyObject2Any(PyTuple_GetItem(types.get(),i));
588 a >>= pret[i];
589 }
591 }
592 }
593 return ret;
594}
595
596static OUString
597lcl_ExceptionMessage(PyObject *const o, OUString const*const pWrapped)
598{
599 OUStringBuffer buf;
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");
604 if (pWrapped)
605 {
606 buf.append("; caught exception: ");
607 buf.append(*pWrapped);
608 }
609 return buf.makeStringAndClear();
610}
611
612// For Python 2.7 - see https://bugs.python.org/issue24161
613// Fills aSeq and returns true if pObj is a valid iterator
614bool Runtime::pyIterUnpack( PyObject *const pObj, Any &a ) const
615{
616 if( !PyIter_Check( pObj ))
617 return false;
618
619 PyObject *pItem = PyIter_Next( pObj );
620 if( !pItem )
621 {
622 if( PyErr_Occurred() )
623 {
624 PyErr_Clear();
625 return false;
626 }
627 return true;
628 }
629
630 ::std::vector<Any> items;
631 do
632 {
633 PyRef rItem( pItem, SAL_NO_ACQUIRE );
634 items.push_back( pyObject2Any( rItem.get() ) );
635 pItem = PyIter_Next( pObj );
636 }
637 while( pItem );
639 return true;
640}
641
643{
644 if (!impl || !impl->cargo->valid)
645 {
646 throw RuntimeException("pyuno runtime must be initialized before calling any2PyObject" );
647 }
648
649 Any a;
650 PyObject *o = source.get();
651 if( Py_None == o )
652 {
653
654 }
655 else if (PyLong_Check (o))
656 {
657 // Convert the Python 3 booleans that are actually of type PyLong.
658 if(o == Py_True)
659 {
660 a <<= true;
661 }
662 else if(o == Py_False)
663 {
664 a <<= false;
665 }
666 else
667 {
668 sal_Int64 l = static_cast<sal_Int64>(PyLong_AsLong (o));
669 if( l < 128 && l >= -128 )
670 {
671 sal_Int8 b = static_cast<sal_Int8>(l);
672 a <<= b;
673 }
674 else if( l <= 0x7fff && l >= -0x8000 )
675 {
676 sal_Int16 s = static_cast<sal_Int16>(l);
677 a <<= s;
678 }
679 else if( l <= SAL_CONST_INT64(0x7fffffff) &&
680 l >= -SAL_CONST_INT64(0x80000000) )
681 {
682 sal_Int32 l32 = static_cast<sal_Int32>(l);
683 a <<= l32;
684 }
685 else
686 {
687 a <<= l;
688 }
689 }
690 }
691 else if (PyFloat_Check (o))
692 {
693 double d = PyFloat_AsDouble (o);
694 a <<= d;
695 }
696 else if (PyBytes_Check(o) || PyUnicode_Check(o))
697 {
698 a <<= pyString2ustring(o);
699 }
700 else if (PyTuple_Check (o))
701 {
702 Sequence<Any> s (PyTuple_Size (o));
703 auto sRange = asNonConstRange(s);
704 for (Py_ssize_t i = 0; i < PyTuple_Size (o); i++)
705 {
706 sRange[i] = pyObject2Any (PyTuple_GetItem (o, i), mode );
707 }
708 a <<= s;
709 }
710 else if (PyList_Check (o))
711 {
712 Py_ssize_t l = PyList_Size (o);
713 Sequence<Any> s (l);
714 auto sRange = asNonConstRange(s);
715 for (Py_ssize_t i = 0; i < l; i++)
716 {
717 sRange[i] = pyObject2Any (PyList_GetItem (o, i), mode );
718 }
719 a <<= s;
720 }
721 else if (!pyIterUnpack (o, a))
722 {
723 Runtime runtime;
724 // should be removed, in case ByteSequence gets derived from String
725 if( PyObject_IsInstance( o, getByteSequenceClass( runtime ).get() ) )
726 {
727 PyRef str(PyObject_GetAttrString( o , "value" ),SAL_NO_ACQUIRE);
729 if( PyBytes_Check( str.get() ) )
730 {
731 seq = Sequence<sal_Int8 > (
732 reinterpret_cast<sal_Int8*>(PyBytes_AsString(str.get())), PyBytes_Size(str.get()));
733 }
734 a <<= seq;
735 }
736 else
737 if( PyObject_IsInstance( o, getTypeClass( runtime ).get() ) )
738 {
739 Type t = PyType2Type( o );
740 a <<= t;
741 }
742 else if( PyObject_IsInstance( o, getEnumClass( runtime ).get() ) )
743 {
744 a = PyEnum2Enum( o );
745 }
746 else if( isInstanceOfStructOrException( o ) )
747 {
748 PyRef struc(PyObject_GetAttrString( o , "value" ),SAL_NO_ACQUIRE);
749 PyUNO * obj = reinterpret_cast<PyUNO*>(struc.get());
750 Reference< XMaterialHolder > holder( obj->members->xInvocation, UNO_QUERY );
751 if( !holder.is( ) )
752 {
753 throw RuntimeException(
754 "struct or exception wrapper does not support XMaterialHolder" );
755 }
756
757 a = holder->getMaterial();
758
759 }
760 else if( PyObject_IsInstance( o, getPyUnoClass().get() ) )
761 {
762 PyUNO* o_pi = reinterpret_cast<PyUNO*>(o);
763 a = o_pi->members->wrappedObject;
764 }
765 else if( PyObject_IsInstance( o, getPyUnoStructClass().get() ) )
766 {
767 PyUNO* o_pi = reinterpret_cast<PyUNO*>(o);
768 Reference<XMaterialHolder> my_mh (o_pi->members->xInvocation, css::uno::UNO_QUERY_THROW);
769 a = my_mh->getMaterial();
770 }
771 else if( PyObject_IsInstance( o, getCharClass( runtime ).get() ) )
772 {
773 a <<= PyChar2Unicode( o );
774 }
775 else if( PyObject_IsInstance( o, getAnyClass( runtime ).get() ) )
776 {
777 if( ACCEPT_UNO_ANY != mode )
778 {
779 throw RuntimeException(
780 "uno.Any instance not accepted during method call, "
781 "use uno.invoke instead" );
782 }
783
784 a = pyObject2Any( PyRef( PyObject_GetAttrString( o , "value" ), SAL_NO_ACQUIRE) );
785 Type t;
786 pyObject2Any( PyRef( PyObject_GetAttrString( o, "type" ), SAL_NO_ACQUIRE ) ) >>= t;
787
788 try
789 {
790 a = getImpl()->cargo->xTypeConverter->convertTo( a, t );
791 }
792 catch( const css::uno::Exception & e )
793 {
794 css::uno::Any anyEx = cppu::getCaughtException();
795 throw WrappedTargetRuntimeException(
796 e.Message, e.Context, anyEx);
797 }
798
799 }
800 else
801 {
802 Reference< XInterface > mappedObject;
803 Reference< XInvocation > adapterObject;
804
805 // instance already mapped out to the world ?
806 PyRef2Adapter::iterator ii = impl->cargo->mappedObjects.find( PyRef( o ) );
807 if( ii != impl->cargo->mappedObjects.end() )
808 {
809 adapterObject = ii->second;
810 }
811
812 if( adapterObject.is() )
813 {
814 // object got already bridged !
815 auto pAdapter = comphelper::getFromUnoTunnel<Adapter>(adapterObject);
816
817 mappedObject = impl->cargo->xAdapterFactory->createAdapter(
818 adapterObject, pAdapter->getWrappedTypes() );
819 }
820 else
821 {
822 try {
823 Sequence<Type> interfaces = invokeGetTypes(*this, o);
824 if (interfaces.getLength())
825 {
826 rtl::Reference<Adapter> pAdapter = new Adapter( o, interfaces );
827 mappedObject =
828 getImpl()->cargo->xAdapterFactory->createAdapter(
829 pAdapter, interfaces );
830
831 // keep a list of exported objects to ensure object identity !
832 impl->cargo->mappedObjects[ PyRef(o) ] =
833 css::uno::WeakReference< XInvocation > ( pAdapter );
834 }
835 } catch (InvocationTargetException const& e) {
836 OUString const msg(lcl_ExceptionMessage(o, &e.Message));
837 throw WrappedTargetRuntimeException( // re-wrap that
838 msg, e.Context, e.TargetException);
839 }
840 }
841 if( mappedObject.is() )
842 {
843 a <<= mappedObject;
844 }
845 else
846 {
847 OUString const msg(lcl_ExceptionMessage(o, nullptr));
848 throw RuntimeException(msg);
849 }
850 }
851 }
852 return a;
853}
854
855Any Runtime::extractUnoException( const PyRef & excType, const PyRef &excValue, const PyRef &excTraceback) const
856{
857 OUString str;
858 Any ret;
859 if( excTraceback.is() )
860 {
861 Exception e;
862 PyRef unoModule;
863 if ( impl )
864 {
865 try
866 {
867 unoModule = impl->cargo->getUnoModule();
868 }
869 catch (const Exception &ei)
870 {
871 e=ei;
872 }
873 }
874 if( unoModule.is() )
875 {
876 PyRef extractTraceback(
877 PyDict_GetItemString(unoModule.get(),"_uno_extract_printable_stacktrace" ) );
878
879 if( PyCallable_Check(extractTraceback.get()) )
880 {
881 PyRef args( PyTuple_New( 1), SAL_NO_ACQUIRE, NOT_NULL );
882 PyTuple_SetItem( args.get(), 0, excTraceback.getAcquired() );
883 PyRef pyStr( PyObject_CallObject( extractTraceback.get(),args.get() ), SAL_NO_ACQUIRE);
884 str = OUString::fromUtf8(PyUnicode_AsUTF8(pyStr.get()));
885 }
886 else
887 {
888 str = "Couldn't find uno._uno_extract_printable_stacktrace";
889 }
890 }
891 else
892 {
893 str = "Could not load uno.py, no stacktrace available";
894 if ( !e.Message.isEmpty() )
895 {
896 str += " (Error loading uno.py: " + e.Message + ")";
897 }
898 }
899
900 }
901 else
902 {
903 // it may occur, that no traceback is given (e.g. only native code below)
904 str = "no traceback available";
905 }
906
907 if( isInstanceOfStructOrException( excValue.get() ) )
908 {
909 ret = pyObject2Any( excValue );
910 }
911 else
912 {
913 OUStringBuffer buf;
914 PyRef typeName( PyObject_Str( excType.get() ), SAL_NO_ACQUIRE );
915 if( typeName.is() )
916 {
917 buf.appendAscii( PyUnicode_AsUTF8( typeName.get() ) );
918 }
919 else
920 {
921 buf.append( "no typename available" );
922 }
923 buf.append( ": " );
924 PyRef valueRep( PyObject_Str( excValue.get() ), SAL_NO_ACQUIRE );
925 if( valueRep.is() )
926 {
927 buf.appendAscii( PyUnicode_AsUTF8( valueRep.get()));
928 }
929 else
930 {
931 buf.append( "Couldn't convert exception value to a string" );
932 }
933 buf.append( ", traceback follows\n" );
934 if( !str.isEmpty() )
935 {
936 buf.append( str );
937 buf.append( "\n" );
938 }
939 else
940 {
941 buf.append( ", no traceback available\n" );
942 }
944 e.Message = buf.makeStringAndClear();
945#if OSL_DEBUG_LEVEL > 0
946 fprintf( stderr, "Python exception: %s\n",
947 OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr() );
948#endif
949 ret <<= e;
950 }
951 return ret;
952}
953
954
955PyThreadAttach::PyThreadAttach( PyInterpreterState *interp)
956 : m_isNewState(false)
957{
958 // note: *may* be called recursively, with PyThreadDetach between - in
959 // that case, don't create *new* PyThreadState but reuse!
960 tstate = PyGILState_GetThisThreadState(); // from TLS, possibly detached
961 if (!tstate)
962 {
963 m_isNewState = true;
964 tstate = PyThreadState_New( interp );
965 }
966 if( !tstate )
967 throw RuntimeException( "Couldn't create a pythreadstate" );
968 PyEval_AcquireThread( tstate);
969}
970
972{
973 if (m_isNewState)
974 { // Clear needs GIL!
975 PyThreadState_Clear( tstate );
976 // note: PyThreadState_Delete(tstate) cannot be called, it will assert
977 // because it requires a PyThreadState to be set, but not the tstate!
978 PyThreadState_DeleteCurrent();
979 }
980 else
981 {
982 PyEval_ReleaseThread( tstate );
983 }
984}
985
987{
988 tstate = PyThreadState_Get();
989 PyEval_ReleaseThread( tstate );
990 // tstate must not be deleted here! lots of pointers to it on the stack
991}
992
997{
998 PyEval_AcquireThread( tstate );
999}
1000
1001
1003{
1004 if( ! dictUnoModule.is() )
1005 {
1007 }
1008 return dictUnoModule;
1009}
1010}
1011
1012/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
XPropertyListType t
double d
css::uno::Type const & get()
Helper class for keeping references to python objects.
Definition: pyuno.hxx:80
bool is() const
returns 1 when the reference points to a python object python object, otherwise 0.
Definition: pyuno.hxx:139
PyObject * get() const noexcept
Definition: pyuno.hxx:99
PyObject * getAcquired() const
Definition: pyuno.hxx:101
PyThreadState * tstate
Definition: pyuno.hxx:273
~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.
PyThreadState * tstate
Definition: pyuno.hxx:301
The pyuno::Runtime class keeps the internal state of the python UNO bridge for the currently in use p...
Definition: pyuno.hxx:164
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.
Definition: pyuno.hxx:242
Runtime()
preconditions: python has been initialized before, the global interpreter lock is held and pyuno has ...
RuntimeImpl * impl
Definition: pyuno.hxx:165
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.
Any value
#define SAL_CONFIGFILE(name)
float v
uno_Any a
size
@ Exception
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
Type
Any SAL_CALL getCaughtException()
int i
ctx
module
args
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
const sal_Int32 NONE
Definition: pyuno_impl.hxx:73
const sal_Int32 CALL
Definition: pyuno_impl.hxx:74
const sal_Int32 ARGS
Definition: pyuno_impl.hxx:75
Definition: pyuno.cxx:72
struct stRuntimeImpl RuntimeImpl
Definition: pyuno.hxx:151
void log(RuntimeCargo *cargo, sal_Int32 level, std::u16string_view logString)
Definition: pyuno_util.cxx:98
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)
Definition: pyuno.cxx:1684
ConversionMode
Definition: pyuno.hxx:153
@ ACCEPT_UNO_ANY
Definition: pyuno.hxx:153
static OUString lcl_ExceptionMessage(PyObject *const o, OUString const *const pWrapped)
PyRef getCharClass(const Runtime &)
Definition: pyuno_type.cxx:110
PyRef getPyUnoStructClass()
PyObject * PyUNO_ByteSequence_new(const css::uno::Sequence< sal_Int8 > &, const Runtime &r)
Definition: pyuno_type.cxx:274
PyObject * PyUNO_char_new(sal_Unicode c, const Runtime &r)
Definition: pyuno_type.cxx:264
static PyTypeObject RuntimeImpl_Type
PyRef ustring2PyString(std::u16string_view source)
Definition: pyuno_util.cxx:51
sal_Unicode PyChar2Unicode(PyObject *o)
Definition: pyuno_type.cxx:126
PyObject * PyUNO_Enum_new(const char *enumBase, const char *enumValue, const Runtime &r)
Definition: pyuno_type.cxx:240
PyRef getTypeClass(const Runtime &)
Definition: pyuno_type.cxx:100
PyRef getEnumClass(const Runtime &)
Definition: pyuno_type.cxx:105
static void getRuntimeImpl(PyRef &globalDict, PyRef &runtimeImpl)
css::uno::Type PyType2Type(PyObject *o)
Definition: pyuno_type.cxx:195
PyRef getByteSequenceClass(const Runtime &)
Definition: pyuno_type.cxx:115
OUString pyString2ustring(PyObject *str)
Definition: pyuno_util.cxx:57
static void readLoggingConfig(sal_Int32 *pLevel, FILE **ppFile)
@ NOT_NULL
definition of a no acquire enum for ctors
Definition: pyuno.hxx:65
PyRef ustring2PyUnicode(const OUString &source)
Definition: pyuno_util.cxx:34
PyRef getClass(const OUString &name, const Runtime &runtime)
css::uno::Any PyEnum2Enum(PyObject *obj)
Definition: pyuno_type.cxx:145
static Sequence< Type > invokeGetTypes(const Runtime &r, PyObject *o)
PyRef getAnyClass(const Runtime &)
Definition: pyuno_type.cxx:120
PyRef PyUNOStruct_new(const css::uno::Any &targetInterface, const css::uno::Reference< css::lang::XSingleServiceFactory > &ssf)
static PyRef importUnoModule()
PyRef getPyUnoClass()
Definition: pyuno.cxx:1679
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
OUString typeName
ConversionMode mode
css::uno::Any wrappedObject
Definition: pyuno_impl.hxx:132
css::uno::Reference< css::script::XInvocation2 > xInvocation
Definition: pyuno_impl.hxx:131
PyObject_HEAD PyUNOInternals * members
Definition: pyuno_impl.hxx:138
css::uno::Reference< css::script::XTypeConverter > xTypeConverter
Definition: pyuno_impl.hxx:217
css::uno::Reference< css::reflection::XIdlReflection > xCoreReflection
Definition: pyuno_impl.hxx:219
css::uno::Reference< css::lang::XSingleServiceFactory > xInvocation
Definition: pyuno_impl.hxx:216
css::uno::Reference< css::container::XHierarchicalNameAccess > xTdMgr
Definition: pyuno_impl.hxx:220
PyRef const & getUnoModule()
css::uno::Reference< css::beans::XIntrospection > xIntrospection
Definition: pyuno_impl.hxx:222
css::uno::Reference< css::script::XInvocationAdapterFactory2 > xAdapterFactory
Definition: pyuno_impl.hxx:221
css::uno::Reference< css::uno::XComponentContext > xContext
Definition: pyuno_impl.hxx:218
static PyRef create(const css::uno::Reference< css::uno::XComponentContext > &xContext)
PyObject_HEAD struct RuntimeCargo * cargo
Definition: pyuno_impl.hxx:238
static void del(PyObject *self)
sal_uInt16 sal_Unicode
signed char sal_Int8