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