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