1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 #include "pyuno_impl.hxx"
25
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>
32 #include <locale.h>
33
34 #include <typelib/typedescription.hxx>
35
36 #include <com/sun/star/beans/XMaterialHolder.hpp>
37
38 #include <vector>
39
40 using rtl::OUString;
41 using rtl::OUStringToOString;
42 using rtl::OUStringBuffer;
43 using rtl::OStringBuffer;
44 using rtl::OString;
45
46 using com::sun::star::uno::Reference;
47 using com::sun::star::uno::XInterface;
48 using com::sun::star::uno::Any;
49 using com::sun::star::uno::TypeDescription;
50 using com::sun::star::uno::Sequence;
51 using com::sun::star::uno::Type;
52 using com::sun::star::uno::UNO_QUERY;
53 using com::sun::star::uno::RuntimeException;
54 using com::sun::star::uno::XComponentContext;
55 using com::sun::star::lang::XSingleServiceFactory;
56 using com::sun::star::lang::XUnoTunnel;
57 using com::sun::star::reflection::XIdlReflection;
58 using com::sun::star::script::XTypeConverter;
59 using com::sun::star::script::XInvocationAdapterFactory2;
60 using com::sun::star::script::XInvocation;
61 using com::sun::star::beans::XMaterialHolder;
62 using com::sun::star::beans::XIntrospection;
63
64 namespace pyuno
65 {
66 #define USTR_ASCII(x) OUString( RTL_CONSTASCII_USTRINGPARAM( x ) )
67
68 static PyTypeObject RuntimeImpl_Type =
69 {
70 PyVarObject_HEAD_INIT(&PyType_Type, 0)
71 const_cast< char * >("pyuno_runtime"),
72 sizeof (RuntimeImpl),
73 0,
74 (destructor) RuntimeImpl::del,
75 (printfunc) 0,
76 (getattrfunc) 0,
77 (setattrfunc) 0,
78 #if PY_MAJOR_VERSION >= 3
79 0,
80 #else
81 (cmpfunc) 0,
82 #endif
83 (reprfunc) 0,
84 0,
85 0,
86 0,
87 (hashfunc) 0,
88 (ternaryfunc) 0,
89 (reprfunc) 0,
90 (getattrofunc)0,
91 (setattrofunc)0,
92 NULL,
93 0,
94 NULL,
95 (traverseproc)0,
96 (inquiry)0,
97 (richcmpfunc)0,
98 0,
99 (getiterfunc)0,
100 (iternextfunc)0,
101 NULL,
102 NULL,
103 NULL,
104 NULL,
105 NULL,
106 (descrgetfunc)0,
107 (descrsetfunc)0,
108 0,
109 (initproc)0,
110 (allocfunc)0,
111 (newfunc)0,
112 (freefunc)0,
113 (inquiry)0,
114 NULL,
115 NULL,
116 NULL,
117 NULL,
118 NULL,
119 (destructor)0
120 #if PY_VERSION_HEX >= 0x02060000
121 , 0
122 #endif
123 };
124
125 /*----------------------------------------------------------------------
126 Runtime implementation
127 -----------------------------------------------------------------------*/
getRuntimeImpl(PyRef & globalDict,PyRef & runtimeImpl)128 static void getRuntimeImpl( PyRef & globalDict, PyRef &runtimeImpl )
129 throw ( com::sun::star::uno::RuntimeException )
130 {
131 PyThreadState * state = PyThreadState_Get();
132 if( ! state )
133 {
134 throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM(
135 "python global interpreter must be held (thread must be attached)" )),
136 Reference< XInterface > () );
137 }
138
139 globalDict = PyRef( PyModule_GetDict(PyImport_AddModule(const_cast< char * >("__main__"))));
140
141 if( ! globalDict.is() ) // FATAL !
142 {
143 throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM(
144 "can't find __main__ module" )), Reference< XInterface > ());
145 }
146 runtimeImpl = PyDict_GetItemString( globalDict.get() , "pyuno_runtime" );
147 }
148
importUnoModule()149 static PyRef importUnoModule( ) throw ( RuntimeException )
150 {
151 PyRef globalDict = PyRef( PyModule_GetDict(PyImport_AddModule(const_cast< char * >("__main__"))));
152 // import the uno module
153 PyRef module( PyImport_ImportModule( const_cast< char * >("uno") ), SAL_NO_ACQUIRE );
154 if( PyErr_Occurred() )
155 {
156 PyRef excType, excValue, excTraceback;
157 PyErr_Fetch( (PyObject **)&excType, (PyObject**)&excValue,(PyObject**)&excTraceback);
158 PyRef str( PyObject_Repr( excTraceback.get() ), SAL_NO_ACQUIRE );
159
160 OUStringBuffer buf;
161 buf.appendAscii( "python object raised an unknown exception (" );
162 PyRef valueRep( PyObject_Repr( excValue.get() ), SAL_NO_ACQUIRE );
163
164 buf.append( pyString2ustring( valueRep.get() ) ).appendAscii( ", traceback follows\n" );
165 buf.append( pyString2ustring( str.get() ) );
166 throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface > () );
167 }
168 PyRef dict( PyModule_GetDict( module.get() ) );
169 return dict;
170 }
171
readLoggingConfig(sal_Int32 * pLevel,FILE ** ppFile)172 static void readLoggingConfig( sal_Int32 *pLevel, FILE **ppFile )
173 {
174 *pLevel = LogLevel::NONE;
175 *ppFile = 0;
176 OUString fileName;
177 osl_getModuleURLFromFunctionAddress(
178 reinterpret_cast< oslGenericFunction >(readLoggingConfig),
179 (rtl_uString **) &fileName );
180 fileName = OUString( fileName.getStr(), fileName.lastIndexOf( '/' )+1 );
181 fileName += OUString::createFromAscii( SAL_CONFIGFILE("pyuno") );
182 rtl::Bootstrap bootstrapHandle( fileName );
183
184 OUString str;
185 if( bootstrapHandle.getFrom( USTR_ASCII( "PYUNO_LOGLEVEL" ), str ) )
186 {
187 if( str.equalsAscii( "NONE" ) )
188 *pLevel = LogLevel::NONE;
189 else if( str.equalsAscii( "CALL" ) )
190 *pLevel = LogLevel::CALL;
191 else if( str.equalsAscii( "ARGS" ) )
192 *pLevel = LogLevel::ARGS;
193 else
194 {
195 fprintf( stderr, "unknown loglevel %s\n",
196 OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
197 }
198 }
199 if( *pLevel > LogLevel::NONE )
200 {
201 *ppFile = stdout;
202 if( bootstrapHandle.getFrom( USTR_ASCII( "PYUNO_LOGTARGET" ), str ) )
203 {
204 if( str.equalsAscii( "stdout" ) )
205 *ppFile = stdout;
206 else if( str.equalsAscii( "stderr" ) )
207 *ppFile = stderr;
208 else
209 {
210 oslProcessInfo data;
211 data.Size = sizeof( data );
212 osl_getProcessInfo(
213 0 , osl_Process_IDENTIFIER , &data );
214 osl_getSystemPathFromFileURL( str.pData, &str.pData);
215 OString o = OUStringToOString( str, osl_getThreadTextEncoding() );
216 o += ".";
217 o += OString::valueOf( (sal_Int32)data.Ident );
218
219 *ppFile = fopen( o.getStr() , "w" );
220 if ( *ppFile )
221 {
222 // do not buffer (useful if e.g. analyzing a crash)
223 setvbuf( *ppFile, 0, _IONBF, 0 );
224 }
225 else
226 {
227 fprintf( stderr, "couldn't create file %s\n",
228 OUStringToOString( str, RTL_TEXTENCODING_UTF8 ).getStr() );
229
230 }
231 }
232 }
233 }
234 }
235
236 /*-------------------------------------------------------------------
237 RuntimeImpl implementations
238 *-------------------------------------------------------------------*/
create(const Reference<XComponentContext> & ctx)239 PyRef stRuntimeImpl::create( const Reference< XComponentContext > &ctx )
240 throw( com::sun::star::uno::RuntimeException )
241 {
242 RuntimeImpl *me = PyObject_New (RuntimeImpl, &RuntimeImpl_Type);
243 if( ! me )
244 throw RuntimeException(
245 OUString( RTL_CONSTASCII_USTRINGPARAM( "cannot instantiate pyuno::RuntimeImpl" ) ),
246 Reference< XInterface > () );
247 me->cargo = 0;
248 // must use a different struct here, as the PyObject_New
249 // makes C++ unusable
250 RuntimeCargo *c = new RuntimeCargo();
251 readLoggingConfig( &(c->logLevel) , &(c->logFile) );
252 log( c, LogLevel::CALL, "Instantiating pyuno bridge" );
253
254 c->valid = 1;
255 c->xContext = ctx;
256 c->xInvocation = Reference< XSingleServiceFactory > (
257 ctx->getServiceManager()->createInstanceWithContext(
258 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.script.Invocation" ) ),
259 ctx ),
260 UNO_QUERY );
261 if( ! c->xInvocation.is() )
262 throw RuntimeException(
263 OUString( RTL_CONSTASCII_USTRINGPARAM( "pyuno: couldn't instantiate invocation service" ) ),
264 Reference< XInterface > () );
265
266 c->xTypeConverter = Reference< XTypeConverter > (
267 ctx->getServiceManager()->createInstanceWithContext(
268 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.script.Converter" ) ),
269 ctx ),
270 UNO_QUERY );
271 if( ! c->xTypeConverter.is() )
272 throw RuntimeException(
273 OUString( RTL_CONSTASCII_USTRINGPARAM( "pyuno: couldn't instantiate typeconverter service" )),
274 Reference< XInterface > () );
275
276 c->xCoreReflection = Reference< XIdlReflection > (
277 ctx->getServiceManager()->createInstanceWithContext(
278 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.reflection.CoreReflection" ) ),
279 ctx ),
280 UNO_QUERY );
281 if( ! c->xCoreReflection.is() )
282 throw RuntimeException(
283 OUString( RTL_CONSTASCII_USTRINGPARAM( "pyuno: couldn't instantiate corereflection service" )),
284 Reference< XInterface > () );
285
286 c->xAdapterFactory = Reference< XInvocationAdapterFactory2 > (
287 ctx->getServiceManager()->createInstanceWithContext(
288 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.script.InvocationAdapterFactory" ) ),
289 ctx ),
290 UNO_QUERY );
291 if( ! c->xAdapterFactory.is() )
292 throw RuntimeException(
293 OUString( RTL_CONSTASCII_USTRINGPARAM( "pyuno: couldn't instantiate invocation adapter factory service" )),
294 Reference< XInterface > () );
295
296 c->xIntrospection = Reference< XIntrospection > (
297 ctx->getServiceManager()->createInstanceWithContext(
298 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.beans.Introspection" ) ),
299 ctx ),
300 UNO_QUERY );
301 if( ! c->xIntrospection.is() )
302 throw RuntimeException(
303 OUString( RTL_CONSTASCII_USTRINGPARAM( "pyuno: couldn't instantiate introspection service" )),
304 Reference< XInterface > () );
305
306 Any a = ctx->getValueByName(OUString(
307 RTL_CONSTASCII_USTRINGPARAM("/singletons/com.sun.star.reflection.theTypeDescriptionManager" )) );
308 a >>= c->xTdMgr;
309 if( ! c->xTdMgr.is() )
310 throw RuntimeException(
311 OUString( RTL_CONSTASCII_USTRINGPARAM( "pyuno: couldn't retrieve typedescriptionmanager" )),
312 Reference< XInterface > () );
313
314 me->cargo =c;
315 return PyRef( reinterpret_cast< PyObject * > ( me ), SAL_NO_ACQUIRE );
316 }
317
del(PyObject * self)318 void stRuntimeImpl::del(PyObject* self)
319 {
320 RuntimeImpl *me = reinterpret_cast< RuntimeImpl * > ( self );
321 if( me->cargo->logFile )
322 fclose( me->cargo->logFile );
323 delete me->cargo;
324 PyObject_Del (self);
325 }
326
327
initialize(const Reference<XComponentContext> & ctx)328 void Runtime::initialize( const Reference< XComponentContext > & ctx )
329 throw ( RuntimeException )
330 {
331 PyRef globalDict, runtime;
332 getRuntimeImpl( globalDict , runtime );
333 RuntimeImpl *impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
334
335 if( runtime.is() && impl->cargo->valid )
336 {
337 throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM(
338 "pyuno runtime has already been initialized before" ) ),
339 Reference< XInterface > () );
340 }
341 PyRef keep( RuntimeImpl::create( ctx ) );
342 PyDict_SetItemString( globalDict.get(), "pyuno_runtime" , keep.get() );
343 Py_XINCREF( keep.get() );
344 }
345
346
isInitialized()347 bool Runtime::isInitialized() throw ( RuntimeException )
348 {
349 PyRef globalDict, runtime;
350 getRuntimeImpl( globalDict , runtime );
351 RuntimeImpl *impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
352 return runtime.is() && impl->cargo->valid;
353 }
354
finalize()355 void Runtime::finalize() throw (RuntimeException)
356 {
357 PyRef globalDict, runtime;
358 getRuntimeImpl( globalDict , runtime );
359 RuntimeImpl *impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
360 if( !runtime.is() || ! impl->cargo->valid )
361 {
362 throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM(
363 "pyuno bridge must have been initialized before finalizing" )),
364 Reference< XInterface > () );
365 }
366 impl->cargo->valid = false;
367 impl->cargo->xInvocation.clear();
368 impl->cargo->xContext.clear();
369 impl->cargo->xTypeConverter.clear();
370 }
371
Runtime()372 Runtime::Runtime() throw( RuntimeException )
373 : impl( 0 )
374 {
375 PyRef globalDict, runtime;
376 getRuntimeImpl( globalDict , runtime );
377 if( ! runtime.is() )
378 {
379 throw RuntimeException(
380 OUString( RTL_CONSTASCII_USTRINGPARAM("pyuno runtime is not initialized, "
381 "(the pyuno.bootstrap needs to be called before using any uno classes)")),
382 Reference< XInterface > () );
383 }
384 impl = reinterpret_cast< RuntimeImpl * > (runtime.get());
385 Py_XINCREF( runtime.get() );
386 }
387
Runtime(const Runtime & r)388 Runtime::Runtime( const Runtime & r )
389 {
390 impl = r.impl;
391 Py_XINCREF( reinterpret_cast< PyObject * >(impl) );
392 }
393
~Runtime()394 Runtime::~Runtime()
395 {
396 Py_XDECREF( reinterpret_cast< PyObject * >(impl) );
397 }
398
operator =(const Runtime & r)399 Runtime & Runtime::operator = ( const Runtime & r )
400 {
401 PyRef temp( reinterpret_cast< PyObject * >(r.impl) );
402 Py_XINCREF( temp.get() );
403 Py_XDECREF( reinterpret_cast< PyObject * >(impl) );
404 impl = r.impl;
405 return *this;
406 }
407
any2PyObject(const Any & a) const408 PyRef Runtime::any2PyObject (const Any &a ) const
409 throw ( com::sun::star::script::CannotConvertException,
410 com::sun::star::lang::IllegalArgumentException,
411 RuntimeException)
412 {
413 if( ! impl->cargo->valid )
414 {
415 throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM(
416 "pyuno runtime must be initialized before calling any2PyObject" )),
417 Reference< XInterface > () );
418 }
419
420 switch (a.getValueTypeClass ())
421 {
422 case typelib_TypeClass_VOID:
423 {
424 Py_INCREF (Py_None);
425 return PyRef(Py_None);
426 }
427 case typelib_TypeClass_CHAR:
428 {
429 sal_Unicode c = *(sal_Unicode*)a.getValue();
430 return PyRef( PyUNO_char_new( c , *this ), SAL_NO_ACQUIRE );
431 }
432 case typelib_TypeClass_BOOLEAN:
433 {
434 sal_Bool b = sal_Bool();
435 if ((a >>= b) && b)
436 return Py_True;
437 else
438 return Py_False;
439 }
440 case typelib_TypeClass_BYTE:
441 case typelib_TypeClass_SHORT:
442 case typelib_TypeClass_UNSIGNED_SHORT:
443 case typelib_TypeClass_LONG:
444 {
445 sal_Int32 l = 0;
446 a >>= l;
447 #if PY_MAJOR_VERSION >= 3
448 return PyRef( PyLong_FromLong (l), SAL_NO_ACQUIRE );
449 #else
450 return PyRef( PyInt_FromLong (l), SAL_NO_ACQUIRE );
451 #endif
452 }
453 case typelib_TypeClass_UNSIGNED_LONG:
454 {
455 sal_uInt32 l = 0;
456 a >>= l;
457 return PyRef( PyLong_FromUnsignedLong (l), SAL_NO_ACQUIRE );
458 }
459 case typelib_TypeClass_HYPER:
460 {
461 sal_Int64 l = 0;
462 a >>= l;
463 return PyRef( PyLong_FromLongLong (l), SAL_NO_ACQUIRE);
464 }
465 case typelib_TypeClass_UNSIGNED_HYPER:
466 {
467 sal_uInt64 l = 0;
468 a >>= l;
469 return PyRef( PyLong_FromUnsignedLongLong (l), SAL_NO_ACQUIRE);
470 }
471 case typelib_TypeClass_FLOAT:
472 {
473 float f = 0.0;
474 a >>= f;
475 return PyRef(PyFloat_FromDouble (f), SAL_NO_ACQUIRE);
476 }
477 case typelib_TypeClass_DOUBLE:
478 {
479 double d = 0.0;
480 a >>= d;
481 return PyRef( PyFloat_FromDouble (d), SAL_NO_ACQUIRE);
482 }
483 case typelib_TypeClass_STRING:
484 {
485 OUString tmp_ostr;
486 a >>= tmp_ostr;
487 return ustring2PyUnicode( tmp_ostr );
488 }
489 case typelib_TypeClass_TYPE:
490 {
491 Type t;
492 a >>= t;
493 OString o = OUStringToOString( t.getTypeName(), RTL_TEXTENCODING_ASCII_US );
494 return PyRef(
495 PyUNO_Type_new (
496 o.getStr(), (com::sun::star::uno::TypeClass)t.getTypeClass(), *this),
497 SAL_NO_ACQUIRE);
498 }
499 case typelib_TypeClass_ANY:
500 {
501 //I don't think this can happen.
502 Py_INCREF (Py_None);
503 return Py_None;
504 }
505 case typelib_TypeClass_ENUM:
506 {
507 sal_Int32 l = *(sal_Int32 *) a.getValue();
508 TypeDescription desc( a.getValueType() );
509 if( desc.is() )
510 {
511 desc.makeComplete();
512 typelib_EnumTypeDescription *pEnumDesc =
513 (typelib_EnumTypeDescription *) desc.get();
514 for( int i = 0 ; i < pEnumDesc->nEnumValues ; i ++ )
515 {
516 if( pEnumDesc->pEnumValues[i] == l )
517 {
518 OString v = OUStringToOString( pEnumDesc->ppEnumNames[i], RTL_TEXTENCODING_ASCII_US);
519 OString e = OUStringToOString( pEnumDesc->aBase.pTypeName, RTL_TEXTENCODING_ASCII_US);
520 return PyRef( PyUNO_Enum_new(e.getStr(),v.getStr(), *this ), SAL_NO_ACQUIRE );
521 }
522 }
523 }
524 OUStringBuffer buf;
525 buf.appendAscii( "Any carries enum " );
526 buf.append( a.getValueType().getTypeName());
527 buf.appendAscii( " with invalid value " ).append( l );
528 throw RuntimeException( buf.makeStringAndClear() , Reference< XInterface > () );
529 }
530 case typelib_TypeClass_EXCEPTION:
531 case typelib_TypeClass_STRUCT:
532 {
533 PyRef excClass = getClass( a.getValueType().getTypeName(), *this );
534 PyRef value = PyRef( PyUNO_new_UNCHECKED (a, getImpl()->cargo->xInvocation), SAL_NO_ACQUIRE);
535 PyRef argsTuple( PyTuple_New( 1 ) , SAL_NO_ACQUIRE );
536 PyTuple_SetItem( argsTuple.get() , 0 , value.getAcquired() );
537 PyRef ret( PyObject_CallObject( excClass.get() , argsTuple.get() ), SAL_NO_ACQUIRE );
538 if( ! ret.is() )
539 {
540 OUStringBuffer buf;
541 buf.appendAscii( "Couldn't instantiate python representation of structered UNO type " );
542 buf.append( a.getValueType().getTypeName() );
543 throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface > () );
544 }
545
546 if( com::sun::star::uno::TypeClass_EXCEPTION == a.getValueTypeClass() )
547 {
548 // add the message in a standard python way !
549 PyRef args( PyTuple_New( 1 ), SAL_NO_ACQUIRE );
550
551 // assuming that the Message is always the first member, wuuuu
552 void *pData = (void*)a.getValue();
553 OUString message = *(OUString * )pData;
554 PyRef pymsg = USTR_TO_PYSTR( message );
555 PyTuple_SetItem( args.get(), 0 , pymsg.getAcquired() );
556 // the exception base functions want to have an "args" tuple,
557 // which contains the message
558 PyObject_SetAttrString( ret.get(), const_cast< char * >("args"), args.get() );
559 }
560 return ret;
561 }
562 case typelib_TypeClass_SEQUENCE:
563 {
564 Sequence<Any> s;
565
566 Sequence< sal_Int8 > byteSequence;
567 if( a >>= byteSequence )
568 {
569 // byte sequence is treated in a special way because of peformance reasons
570 // @since 0.9.2
571 return PyRef( PyUNO_ByteSequence_new( byteSequence, *this ), SAL_NO_ACQUIRE );
572 }
573 else
574 {
575 Reference< XTypeConverter > tc = getImpl()->cargo->xTypeConverter;
576 Reference< XSingleServiceFactory > ssf = getImpl()->cargo->xInvocation;
577 tc->convertTo (a, ::getCppuType (&s)) >>= s;
578 PyRef tuple( PyTuple_New (s.getLength()), SAL_NO_ACQUIRE);
579 int i=0;
580 OUString errMsg;
581 try
582 {
583 for ( i = 0; i < s.getLength (); i++)
584 {
585 PyRef element;
586 element = any2PyObject (tc->convertTo (s[i], s[i].getValueType() ));
587 OSL_ASSERT( element.is() );
588 PyTuple_SetItem( tuple.get(), i, element.getAcquired() );
589 }
590 }
591 catch( com::sun::star::uno::Exception & )
592 {
593 for( ; i < s.getLength() ; i ++ )
594 {
595 Py_INCREF( Py_None );
596 PyTuple_SetItem( tuple.get(), i, Py_None );
597 }
598 throw;
599 }
600 return tuple;
601 }
602 }
603 case typelib_TypeClass_INTERFACE:
604 {
605 Reference< XUnoTunnel > tunnel;
606 a >>= tunnel;
607 if( tunnel.is() )
608 {
609 sal_Int64 that = tunnel->getSomething( ::pyuno::Adapter::getUnoTunnelImplementationId() );
610 if( that )
611 return ((Adapter*)sal::static_int_cast< sal_IntPtr >(that))->getWrappedObject();
612 }
613 //This is just like the struct case:
614 return PyRef( PyUNO_new (a, getImpl()->cargo->xInvocation), SAL_NO_ACQUIRE );
615 }
616 default:
617 {
618 OUStringBuffer buf;
619 buf.appendAscii( "Unknonwn UNO type class " );
620 buf.append( (sal_Int32 ) a.getValueTypeClass() );
621 throw RuntimeException(buf.makeStringAndClear( ), Reference< XInterface > () );
622 }
623 }
624 //We shouldn't be here...
625 Py_INCREF( Py_None );
626 return Py_None;
627 }
628
invokeGetTypes(const Runtime & r,PyObject * o)629 static Sequence< Type > invokeGetTypes( const Runtime & r , PyObject * o )
630 {
631 Sequence< Type > ret;
632
633 PyRef method( PyObject_GetAttrString( o , const_cast< char * >("getTypes") ), SAL_NO_ACQUIRE );
634 raiseInvocationTargetExceptionWhenNeeded( r );
635 if( method.is() && PyCallable_Check( method.get() ) )
636 {
637 PyRef types( PyObject_CallObject( method.get(), 0 ) , SAL_NO_ACQUIRE );
638 raiseInvocationTargetExceptionWhenNeeded( r );
639 if( types.is() && PyTuple_Check( types.get() ) )
640 {
641 int size = PyTuple_Size( types.get() );
642
643 // add the XUnoTunnel interface for uno object identity concept (hack)
644 ret.realloc( size + 1 );
645 for( int i = 0 ; i < size ; i ++ )
646 {
647 Any a = r.pyObject2Any(PyTuple_GetItem(types.get(),i));
648 a >>= ret[i];
649 }
650 ret[size] = getCppuType( (Reference< com::sun::star::lang::XUnoTunnel> *) 0 );
651 }
652 }
653 return ret;
654 }
655
pyObject2Any(const PyRef & source,enum ConversionMode mode) const656 Any Runtime::pyObject2Any ( const PyRef & source, enum ConversionMode mode ) const
657 throw ( com::sun::star::uno::RuntimeException )
658 {
659 if( ! impl->cargo->valid )
660 {
661 throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM(
662 "pyuno runtime must be initialized before calling any2PyObject" )),
663 Reference< XInterface > () );
664 }
665
666 Any a;
667 PyObject *o = source.get();
668 if( Py_None == o )
669 {
670
671 }
672 #if PY_MAJOR_VERSION >= 3 // Python 3 has no PyInt
673 else if (PyBool_Check(o))
674 {
675 if( o == Py_True )
676 {
677 sal_Bool b = sal_True;
678 a = Any( &b, getBooleanCppuType() );
679 }
680 else
681 {
682 sal_Bool b = sal_False;
683 a = Any( &b, getBooleanCppuType() );
684 }
685 }
686 #else
687 else if (PyInt_Check (o))
688 {
689 if( o == Py_True )
690 {
691 sal_Bool b = sal_True;
692 a = Any( &b, getBooleanCppuType() );
693 }
694 else if ( o == Py_False )
695 {
696 sal_Bool b = sal_False;
697 a = Any( &b, getBooleanCppuType() );
698 }
699 else
700 {
701 sal_Int32 l = (sal_Int32) PyInt_AsLong( o );
702 if( l < 128 && l >= -128 )
703 {
704 sal_Int8 b = (sal_Int8 ) l;
705 a <<= b;
706 }
707 else if( l <= 0x7fff && l >= -0x8000 )
708 {
709 sal_Int16 s = (sal_Int16) l;
710 a <<= s;
711 }
712 else
713 {
714 a <<= l;
715 }
716 }
717 }
718 #endif // Python 3 has no PyInt
719 else if (PyLong_Check (o))
720 {
721 sal_Int64 l = (sal_Int64)PyLong_AsLong (o);
722 if( l < 128 && l >= -128 )
723 {
724 sal_Int8 b = (sal_Int8 ) l;
725 a <<= b;
726 }
727 else if( l <= 0x7fff && l >= -0x8000 )
728 {
729 sal_Int16 s = (sal_Int16) l;
730 a <<= s;
731 }
732 else if( l <= SAL_CONST_INT64(0x7fffffff) &&
733 l >= -SAL_CONST_INT64(0x80000000) )
734 {
735 sal_Int32 l32 = (sal_Int32) l;
736 a <<= l32;
737 }
738 else
739 {
740 a <<= l;
741 }
742 }
743 else if (PyFloat_Check (o))
744 {
745 double d = PyFloat_AsDouble (o);
746 a <<= d;
747 }
748 #if PY_MAJOR_VERSION < 3
749 else if (PyBytes_Check (o))
750 a <<= pyString2ustring(o);
751 #endif
752 else if( PyUnicode_Check( o ) )
753 a <<= pyString2ustring(o);
754 else if (PyTuple_Check (o))
755 {
756 Sequence<Any> s (PyTuple_Size (o));
757 for (int i = 0; i < PyTuple_Size (o); i++)
758 {
759 s[i] = pyObject2Any (PyTuple_GetItem (o, i), mode );
760 }
761 a <<= s;
762 }
763 else
764 {
765 Runtime runtime;
766 // should be removed, in case ByteSequence gets derived from String
767 if( PyObject_IsInstance( o, getByteSequenceClass( runtime ).get() ) )
768 {
769 PyRef str(PyObject_GetAttrString( o , const_cast< char * >("value") ),SAL_NO_ACQUIRE);
770 Sequence< sal_Int8 > seq;
771 if( PyBytes_Check( str.get() ) )
772 {
773 seq = Sequence<sal_Int8 > (
774 (sal_Int8*) PyBytes_AsString(str.get()), PyBytes_Size(str.get()));
775 }
776 #if PY_MAJOR_VERSION >= 3
777 else if ( PyByteArray_Check( str.get() ) )
778 {
779 seq = Sequence< sal_Int8 >(
780 (sal_Int8 *) PyByteArray_AS_STRING(str.get()), PyByteArray_GET_SIZE(str.get()));
781 }
782 #endif
783 a <<= seq;
784 }
785 else
786 if( PyObject_IsInstance( o, getTypeClass( runtime ).get() ) )
787 {
788 Type t = PyType2Type( o );
789 a <<= t;
790 }
791 else if( PyObject_IsInstance( o, getEnumClass( runtime ).get() ) )
792 {
793 a = PyEnum2Enum( o );
794 }
795 else if( isInstanceOfStructOrException( o ) )
796 {
797 PyRef struc(PyObject_GetAttrString( o , const_cast< char * >("value") ),SAL_NO_ACQUIRE);
798 PyUNO * obj = (PyUNO*)struc.get();
799 Reference< XMaterialHolder > holder( obj->members->xInvocation, UNO_QUERY );
800 if( holder.is( ) )
801 a = holder->getMaterial();
802 else
803 {
804 throw RuntimeException(
805 USTR_ASCII( "struct or exception wrapper does not support XMaterialHolder" ),
806 Reference< XInterface > () );
807 }
808 }
809 else if( PyObject_IsInstance( o, getPyUnoClass().get() ) )
810 {
811 PyUNO* o_pi;
812 o_pi = (PyUNO*) o;
813 if (o_pi->members->wrappedObject.getValueTypeClass () ==
814 com::sun::star::uno::TypeClass_STRUCT ||
815 o_pi->members->wrappedObject.getValueTypeClass () ==
816 com::sun::star::uno::TypeClass_EXCEPTION)
817 {
818 Reference<XMaterialHolder> my_mh (o_pi->members->xInvocation, UNO_QUERY);
819
820 if (!my_mh.is ())
821 {
822 throw RuntimeException(
823 USTR_ASCII( "struct wrapper does not support XMaterialHolder" ),
824 Reference< XInterface > () );
825 }
826 else
827 a = my_mh->getMaterial ();
828 }
829 else
830 {
831 a = o_pi->members->wrappedObject;
832 }
833 }
834 else if( PyObject_IsInstance( o, getCharClass( runtime ).get() ) )
835 {
836 sal_Unicode c = PyChar2Unicode( o );
837 a.setValue( &c, getCharCppuType( ));
838 }
839 else if( PyObject_IsInstance( o, getAnyClass( runtime ).get() ) )
840 {
841 if( ACCEPT_UNO_ANY == mode )
842 {
843 a = pyObject2Any( PyRef( PyObject_GetAttrString( o , const_cast< char * >("value") ), SAL_NO_ACQUIRE) );
844 Type t;
845 pyObject2Any( PyRef( PyObject_GetAttrString( o, const_cast< char * >("type") ), SAL_NO_ACQUIRE ) ) >>= t;
846
847 try
848 {
849 a = getImpl()->cargo->xTypeConverter->convertTo( a, t );
850 }
851 catch( com::sun::star::uno::Exception & e )
852 {
853 throw RuntimeException( e.Message, e.Context );
854 }
855 }
856 else
857 {
858 throw RuntimeException(
859 OUString( RTL_CONSTASCII_USTRINGPARAM(
860 "uno.Any instance not accepted during method call, "
861 "use uno.invoke instead" ) ),
862 Reference< XInterface > () );
863 }
864 }
865 else
866 {
867 Reference< XInterface > mappedObject;
868 Reference< XInvocation > adapterObject;
869
870 // instance already mapped out to the world ?
871 PyRef2Adapter::iterator ii = impl->cargo->mappedObjects.find( PyRef( o ) );
872 if( ii != impl->cargo->mappedObjects.end() )
873 {
874 adapterObject = ii->second;
875 }
876
877 if( adapterObject.is() )
878 {
879 // object got already bridged !
880 Reference< com::sun::star::lang::XUnoTunnel > tunnel( adapterObject, UNO_QUERY );
881
882 Adapter *pAdapter = ( Adapter * )
883 sal::static_int_cast< sal_IntPtr >(
884 tunnel->getSomething(
885 ::pyuno::Adapter::getUnoTunnelImplementationId() ) );
886
887 mappedObject = impl->cargo->xAdapterFactory->createAdapter(
888 adapterObject, pAdapter->getWrappedTypes() );
889 }
890 else
891 {
892 Sequence< Type > interfaces = invokeGetTypes( *this, o );
893 if( interfaces.getLength() )
894 {
895 Adapter *pAdapter = new Adapter( o, interfaces );
896 mappedObject =
897 getImpl()->cargo->xAdapterFactory->createAdapter(
898 pAdapter, interfaces );
899
900 // keep a list of exported objects to ensure object identity !
901 impl->cargo->mappedObjects[ PyRef(o) ] =
902 com::sun::star::uno::WeakReference< XInvocation > ( pAdapter );
903 }
904 }
905 if( mappedObject.is() )
906 {
907 a = com::sun::star::uno::makeAny( mappedObject );
908 }
909 else
910 {
911 OUStringBuffer buf;
912 buf.appendAscii( "Couldn't convert " );
913 PyRef reprString( PyObject_Str( o ) , SAL_NO_ACQUIRE );
914 buf.append( pyString2ustring( reprString.get() ) );
915 buf.appendAscii( " to a UNO type" );
916 throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface > () );
917 }
918 }
919 }
920 return a;
921 }
922
extractUnoException(const PyRef & excType,const PyRef & excValue,const PyRef & excTraceback) const923 Any Runtime::extractUnoException( const PyRef & excType, const PyRef &excValue, const PyRef &excTraceback) const
924 {
925 PyRef str;
926 Any ret;
927 if( excTraceback.is() )
928 {
929 PyRef unoModule( impl ? impl->cargo->getUnoModule() : 0 );
930 if( unoModule.is() )
931 {
932 PyRef extractTraceback(
933 PyDict_GetItemString(unoModule.get(),"_uno_extract_printable_stacktrace" ) );
934
935 if( extractTraceback.is() )
936 {
937 PyRef args( PyTuple_New( 1), SAL_NO_ACQUIRE );
938 PyTuple_SetItem( args.get(), 0, excTraceback.getAcquired() );
939 str = PyRef( PyObject_CallObject( extractTraceback.get(),args.get() ), SAL_NO_ACQUIRE);
940 }
941 else
942 {
943 str = PyRef(
944 PyBytes_FromString( "Couldn't find uno._uno_extract_printable_stacktrace" ),
945 SAL_NO_ACQUIRE );
946 }
947 }
948 else
949 {
950 str = PyRef(
951 PyBytes_FromString( "Couldn't find uno.py, no stacktrace available" ),
952 SAL_NO_ACQUIRE );
953 }
954
955 }
956 else
957 {
958 // it may occur, that no traceback is given (e.g. only native code below)
959 str = PyRef( PyBytes_FromString( "no traceback available" ), SAL_NO_ACQUIRE);
960 }
961
962 if( isInstanceOfStructOrException( excValue.get() ) )
963 {
964 ret = pyObject2Any( excValue );
965 }
966 else
967 {
968 OUStringBuffer buf;
969 PyRef typeName( PyObject_Str( excType.get() ), SAL_NO_ACQUIRE );
970 if( typeName.is() )
971 {
972 buf.append( pyString2ustring( typeName.get() ) );
973 }
974 else
975 {
976 buf.appendAscii( "no typename available" );
977 }
978 buf.appendAscii( ": " );
979 PyRef valueRep( PyObject_Str( excValue.get() ), SAL_NO_ACQUIRE );
980 if( valueRep.is() )
981 {
982 buf.append( pyString2ustring( valueRep.get()));
983 }
984 else
985 {
986 buf.appendAscii( "Couldn't convert exception value to a string" );
987 }
988 buf.appendAscii( ", traceback follows\n" );
989 if( str.is() )
990 {
991 buf.append( pyString2ustring( str.get() ) );
992 }
993 else
994 {
995 buf.appendAscii( ", no traceback available\n" );
996 }
997 RuntimeException e;
998 e.Message = buf.makeStringAndClear();
999 ret = com::sun::star::uno::makeAny( e );
1000 }
1001 return ret;
1002 }
1003
1004
1005 static const char * g_NUMERICID = "pyuno.lcNumeric";
1006 static ::std::vector< rtl::OString > g_localeList;
1007
ensureUnlimitedLifetime(const char * str)1008 static const char *ensureUnlimitedLifetime( const char *str )
1009 {
1010 int size = g_localeList.size();
1011 int i;
1012 for( i = 0 ; i < size ; i ++ )
1013 {
1014 if( 0 == strcmp( g_localeList[i].getStr(), str ) )
1015 break;
1016 }
1017 if( i == size )
1018 {
1019 g_localeList.push_back( str );
1020 }
1021 return g_localeList[i].getStr();
1022 }
1023
1024
PyThreadAttach(PyInterpreterState * interp)1025 PyThreadAttach::PyThreadAttach( PyInterpreterState *interp)
1026 throw ( com::sun::star::uno::RuntimeException )
1027 {
1028 tstate = PyThreadState_New( interp );
1029 if( !tstate )
1030 throw RuntimeException(
1031 OUString(RTL_CONSTASCII_USTRINGPARAM( "Couldn't create a pythreadstate" ) ),
1032 Reference< XInterface > () );
1033 PyEval_AcquireThread( tstate);
1034 // set LC_NUMERIC to "C"
1035 const char * oldLocale =
1036 ensureUnlimitedLifetime( setlocale( LC_NUMERIC, 0 ) );
1037 setlocale( LC_NUMERIC, "C" );
1038 PyRef locale( // python requires C locale
1039 PyLong_FromVoidPtr( (void*)oldLocale ), SAL_NO_ACQUIRE);
1040 PyDict_SetItemString(
1041 PyThreadState_GetDict(), g_NUMERICID, locale.get() );
1042 }
1043
~PyThreadAttach()1044 PyThreadAttach::~PyThreadAttach()
1045 {
1046 PyObject *value =
1047 PyDict_GetItemString( PyThreadState_GetDict( ), g_NUMERICID );
1048 if( value )
1049 setlocale( LC_NUMERIC, (const char * ) PyLong_AsVoidPtr( value ) );
1050 PyThreadState_Clear( tstate );
1051 PyEval_ReleaseThread( tstate );
1052 PyThreadState_Delete( tstate );
1053
1054 }
1055
PyThreadDetach()1056 PyThreadDetach::PyThreadDetach() throw ( com::sun::star::uno::RuntimeException )
1057 {
1058 tstate = PyThreadState_Get();
1059 PyObject *value =
1060 PyDict_GetItemString( PyThreadState_GetDict( ), g_NUMERICID );
1061 if( value )
1062 setlocale( LC_NUMERIC, (const char * ) PyLong_AsVoidPtr( value ) );
1063 PyEval_ReleaseThread( tstate );
1064 }
1065
1066 /** Acquires the global interpreter lock again
1067
1068 */
~PyThreadDetach()1069 PyThreadDetach::~PyThreadDetach()
1070 {
1071 PyEval_AcquireThread( tstate );
1072 // PyObject *value =
1073 // PyDict_GetItemString( PyThreadState_GetDict( ), g_NUMERICID );
1074
1075 // python requires C LC_NUMERIC locale,
1076 // always set even when it is already "C"
1077 setlocale( LC_NUMERIC, "C" );
1078 }
1079
1080
getUnoModule()1081 PyRef RuntimeCargo::getUnoModule()
1082 {
1083 if( ! dictUnoModule.is() )
1084 {
1085 dictUnoModule = importUnoModule();
1086 }
1087 return dictUnoModule;
1088 }
1089 }
1090