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