xref: /aoo41x/main/pyuno/source/module/pyuno.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include "pyuno_impl.hxx"
29 
30 #include <rtl/strbuf.hxx>
31 #include <rtl/ustrbuf.hxx>
32 
33 #include <osl/thread.h>
34 
35 #include <com/sun/star/lang/XServiceInfo.hpp>
36 #include <com/sun/star/lang/XTypeProvider.hpp>
37 #include <com/sun/star/beans/XPropertySet.hpp>
38 #include <com/sun/star/beans/XMaterialHolder.hpp>
39 
40 #define TO_ASCII(x) OUStringToOString( x , RTL_TEXTENCODING_ASCII_US).getStr()
41 
42 using rtl::OStringBuffer;
43 using rtl::OUStringBuffer;
44 using rtl::OUStringToOString;
45 using rtl::OUString;
46 using com::sun::star::uno::Sequence;
47 using com::sun::star::uno::Reference;
48 using com::sun::star::uno::XInterface;
49 using com::sun::star::uno::Any;
50 using com::sun::star::uno::makeAny;
51 using com::sun::star::uno::UNO_QUERY;
52 using com::sun::star::uno::Type;
53 using com::sun::star::uno::TypeClass;
54 using com::sun::star::uno::RuntimeException;
55 using com::sun::star::uno::Exception;
56 using com::sun::star::uno::XComponentContext;
57 using com::sun::star::lang::XSingleServiceFactory;
58 using com::sun::star::lang::XServiceInfo;
59 using com::sun::star::lang::XTypeProvider;
60 using com::sun::star::script::XTypeConverter;
61 using com::sun::star::script::XInvocation2;
62 using com::sun::star::beans::XMaterialHolder;
63 
64 namespace pyuno
65 {
66 
67 PyObject *PyUNO_str( PyObject * self );
68 
69 void PyUNO_del (PyObject* self)
70 {
71     PyUNO* me = reinterpret_cast< PyUNO* > (self);
72     {
73         PyThreadDetach antiguard;
74         delete me->members;
75     }
76     PyObject_Del (self);
77 }
78 
79 
80 
81 OUString val2str( const void * pVal, typelib_TypeDescriptionReference * pTypeRef , sal_Int32 mode ) SAL_THROW( () )
82 {
83 	OSL_ASSERT( pVal );
84 	if (pTypeRef->eTypeClass == typelib_TypeClass_VOID)
85 		return OUString( RTL_CONSTASCII_USTRINGPARAM("void") );
86 
87 	OUStringBuffer buf( 64 );
88 	buf.append( (sal_Unicode)'(' );
89 	buf.append( pTypeRef->pTypeName );
90 	buf.append( (sal_Unicode)')' );
91 
92 	switch (pTypeRef->eTypeClass)
93 	{
94 	case typelib_TypeClass_INTERFACE:
95     {
96 		buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") );
97 		buf.append( reinterpret_cast< sal_IntPtr >(*(void **)pVal), 16 );
98         if( VAL2STR_MODE_DEEP == mode )
99         {
100             buf.appendAscii( "{" );        Reference< XInterface > r = *( Reference< XInterface > * ) pVal;
101             Reference< XServiceInfo > serviceInfo( r, UNO_QUERY);
102             Reference< XTypeProvider > typeProvider(r,UNO_QUERY);
103             if( serviceInfo.is() )
104             {
105                 buf.appendAscii("implementationName=" );
106                 buf.append(serviceInfo->getImplementationName() );
107                 buf.appendAscii(", supportedServices={" );
108                 Sequence< OUString > seq = serviceInfo->getSupportedServiceNames();
109                 for( int i = 0 ; i < seq.getLength() ; i ++ )
110                 {
111                     buf.append( seq[i] );
112                     if( i +1 != seq.getLength() )
113                         buf.appendAscii( "," );
114                 }
115                 buf.appendAscii("}");
116             }
117 
118             if( typeProvider.is() )
119             {
120                 buf.appendAscii(", supportedInterfaces={" );
121                 Sequence< Type > seq (typeProvider->getTypes());
122                 for( int i = 0 ; i < seq.getLength() ; i ++ )
123                 {
124                     buf.append(seq[i].getTypeName());
125                     if( i +1 != seq.getLength() )
126                         buf.appendAscii( "," );
127                 }
128                 buf.appendAscii("}");
129             }
130             buf.appendAscii( "}" );
131         }
132 
133 		break;
134     }
135 	case typelib_TypeClass_UNION:
136 	{
137 //  		typelib_TypeDescription * pTypeDescr = 0;
138 //  		TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
139 //  		buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{ ") );
140 //  		buf.append( val2str( (char *)pVal + ((typelib_UnionTypeDescription *)pTypeDescr)->nValueOffset,
141 //  							 union_getSetType( pVal, pTypeDescr ) ) );
142 //  		buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" }") );
143 //  		TYPELIB_DANGER_RELEASE( pTypeDescr );
144 		break;
145 	}
146 	case typelib_TypeClass_STRUCT:
147 	case typelib_TypeClass_EXCEPTION:
148 	{
149 		buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{ ") );
150 		typelib_TypeDescription * pTypeDescr = 0;
151 		TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
152 		OSL_ASSERT( pTypeDescr );
153 
154 		typelib_CompoundTypeDescription * pCompType = (typelib_CompoundTypeDescription *)pTypeDescr;
155 		sal_Int32 nDescr = pCompType->nMembers;
156 
157 		if (pCompType->pBaseTypeDescription)
158 		{
159 			buf.append( val2str( pVal, ((typelib_TypeDescription *)pCompType->pBaseTypeDescription)->pWeakRef,mode ) );
160 			if (nDescr)
161 				buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", ") );
162 		}
163 
164 		typelib_TypeDescriptionReference ** ppTypeRefs = pCompType->ppTypeRefs;
165 		sal_Int32 * pMemberOffsets = pCompType->pMemberOffsets;
166 		rtl_uString ** ppMemberNames = pCompType->ppMemberNames;
167 
168 		for ( sal_Int32 nPos = 0; nPos < nDescr; ++nPos )
169 		{
170 			buf.append( ppMemberNames[nPos] );
171 			buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" = ") );
172 			typelib_TypeDescription * pMemberType = 0;
173 			TYPELIB_DANGER_GET( &pMemberType, ppTypeRefs[nPos] );
174 			buf.append( val2str( (char *)pVal + pMemberOffsets[nPos], pMemberType->pWeakRef, mode ) );
175 			TYPELIB_DANGER_RELEASE( pMemberType );
176 			if (nPos < (nDescr -1))
177 				buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", ") );
178 		}
179 
180 		TYPELIB_DANGER_RELEASE( pTypeDescr );
181 
182 		buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" }") );
183 		break;
184 	}
185 	case typelib_TypeClass_SEQUENCE:
186 	{
187 		typelib_TypeDescription * pTypeDescr = 0;
188 		TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
189 
190 		uno_Sequence * pSequence = *(uno_Sequence **)pVal;
191 		typelib_TypeDescription * pElementTypeDescr = 0;
192 		TYPELIB_DANGER_GET( &pElementTypeDescr, ((typelib_IndirectTypeDescription *)pTypeDescr)->pType );
193 
194 		sal_Int32 nElementSize = pElementTypeDescr->nSize;
195 		sal_Int32 nElements	   = pSequence->nElements;
196 
197 		if (nElements)
198 		{
199 			buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{ ") );
200 			char * pElements = pSequence->elements;
201 			for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos )
202 			{
203 				buf.append( val2str( pElements + (nElementSize * nPos), pElementTypeDescr->pWeakRef, mode ) );
204 				if (nPos < (nElements -1))
205 					buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", ") );
206 			}
207 			buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" }") );
208 		}
209 		else
210 		{
211 			buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{}") );
212 		}
213 		TYPELIB_DANGER_RELEASE( pElementTypeDescr );
214 		TYPELIB_DANGER_RELEASE( pTypeDescr );
215 		break;
216 	}
217 	case typelib_TypeClass_ANY:
218 		buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{ ") );
219 		buf.append( val2str( ((uno_Any *)pVal)->pData,
220 							 ((uno_Any *)pVal)->pType ,
221                              mode) );
222 		buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" }") );
223 		break;
224 	case typelib_TypeClass_TYPE:
225 		buf.append( (*(typelib_TypeDescriptionReference **)pVal)->pTypeName );
226 		break;
227 	case typelib_TypeClass_STRING:
228 		buf.append( (sal_Unicode)'\"' );
229 		buf.append( *(rtl_uString **)pVal );
230 		buf.append( (sal_Unicode)'\"' );
231 		break;
232 	case typelib_TypeClass_ENUM:
233 	{
234 		typelib_TypeDescription * pTypeDescr = 0;
235 		TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
236 
237 		sal_Int32 * pValues = ((typelib_EnumTypeDescription *)pTypeDescr)->pEnumValues;
238 		sal_Int32 nPos = ((typelib_EnumTypeDescription *)pTypeDescr)->nEnumValues;
239 		while (nPos--)
240 		{
241 			if (pValues[nPos] == *(int *)pVal)
242 				break;
243 		}
244 		if (nPos >= 0)
245 			buf.append( ((typelib_EnumTypeDescription *)pTypeDescr)->ppEnumNames[nPos] );
246 		else
247 			buf.append( (sal_Unicode)'?' );
248 
249 		TYPELIB_DANGER_RELEASE( pTypeDescr );
250 		break;
251 	}
252 	case typelib_TypeClass_BOOLEAN:
253 		if (*(sal_Bool *)pVal)
254 			buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("true") );
255 		else
256 			buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("false") );
257 		break;
258 	case typelib_TypeClass_CHAR:
259 		buf.append( (sal_Unicode)'\'' );
260 		buf.append( *(sal_Unicode *)pVal );
261 		buf.append( (sal_Unicode)'\'' );
262 		break;
263 	case typelib_TypeClass_FLOAT:
264 		buf.append( *(float *)pVal );
265 		break;
266 	case typelib_TypeClass_DOUBLE:
267 		buf.append( *(double *)pVal );
268 		break;
269 	case typelib_TypeClass_BYTE:
270 		buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") );
271 		buf.append( (sal_Int32)*(sal_Int8 *)pVal, 16 );
272 		break;
273 	case typelib_TypeClass_SHORT:
274 		buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") );
275 		buf.append( (sal_Int32)*(sal_Int16 *)pVal, 16 );
276 		break;
277 	case typelib_TypeClass_UNSIGNED_SHORT:
278 		buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") );
279 		buf.append( (sal_Int32)*(sal_uInt16 *)pVal, 16 );
280 		break;
281 	case typelib_TypeClass_LONG:
282 		buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") );
283 		buf.append( *(sal_Int32 *)pVal, 16 );
284 		break;
285 	case typelib_TypeClass_UNSIGNED_LONG:
286 		buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") );
287 		buf.append( (sal_Int64)*(sal_uInt32 *)pVal, 16 );
288 		break;
289 	case typelib_TypeClass_HYPER:
290 	case typelib_TypeClass_UNSIGNED_HYPER:
291 		buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") );
292 #if defined(GCC) && defined(SPARC)
293 		{
294 			sal_Int64 aVal;
295 			*(sal_Int32 *)&aVal = *(sal_Int32 *)pVal;
296 			*((sal_Int32 *)&aVal +1)= *((sal_Int32 *)pVal +1);
297 			buf.append( aVal, 16 );
298 		}
299 #else
300 		buf.append( *(sal_Int64 *)pVal, 16 );
301 #endif
302 		break;
303 
304 	case typelib_TypeClass_VOID:
305 	case typelib_TypeClass_ARRAY:
306 	case typelib_TypeClass_UNKNOWN:
307 	case typelib_TypeClass_SERVICE:
308 	case typelib_TypeClass_MODULE:
309 	default:
310 		buf.append( (sal_Unicode)'?' );
311 	}
312 
313 	return buf.makeStringAndClear();
314 }
315 
316 
317 PyObject *PyUNO_repr( PyObject  * self )
318 {
319     PyUNO *me = (PyUNO * ) self;
320     PyObject * ret = 0;
321 
322     if( me->members->wrappedObject.getValueType().getTypeClass()
323         == com::sun::star::uno::TypeClass_EXCEPTION )
324     {
325         Reference< XMaterialHolder > rHolder(me->members->xInvocation,UNO_QUERY);
326         if( rHolder.is() )
327         {
328             Any a = rHolder->getMaterial();
329             Exception e;
330             a >>= e;
331             ret = ustring2PyUnicode(e.Message ).getAcquired();
332         }
333     }
334     else
335     {
336         ret = PyUNO_str( self );
337     }
338     return ret;
339 }
340 
341 PyObject *PyUNO_invoke( PyObject *object, const char *name , PyObject *args )
342 {
343     PyRef ret;
344     try
345     {
346         Runtime runtime;
347 
348         PyRef paras,callable;
349         if( PyObject_IsInstance( object, getPyUnoClass( runtime ).get() ) )
350         {
351             PyUNO* me = (PyUNO*) object;
352             OUString attrName = OUString::createFromAscii(name);
353             if (! me->members->xInvocation->hasMethod (attrName))
354             {
355                 OUStringBuffer buf;
356                 buf.appendAscii( "Attribute " );
357                 buf.append( attrName );
358                 buf.appendAscii( " unknown" );
359                 throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface > () );
360             }
361             callable = PyUNO_callable_new (
362                 me->members->xInvocation,
363                 attrName,
364                 runtime.getImpl()->cargo->xInvocation,
365                 runtime.getImpl()->cargo->xTypeConverter,
366                 ACCEPT_UNO_ANY);
367             paras = args;
368         }
369         else
370         {
371             // clean the tuple from uno.Any !
372             int size = PyTuple_Size( args );
373             { // for CC, keeping ref-count of tuple being 1
374             paras = PyRef(PyTuple_New( size ), SAL_NO_ACQUIRE);
375             }
376             for( int i = 0 ; i < size ;i ++ )
377             {
378                 PyObject * element = PyTuple_GetItem( args , i );
379                 if( PyObject_IsInstance( element , getAnyClass( runtime ).get() ) )
380                 {
381                     element = PyObject_GetAttrString(
382                         element, const_cast< char * >("value") );
383                 }
384                 else
385                 {
386                     Py_XINCREF( element );
387                 }
388                 PyTuple_SetItem( paras.get(), i , element );
389             }
390             callable = PyRef( PyObject_GetAttrString( object , (char*)name ), SAL_NO_ACQUIRE );
391             if( !callable.is() )
392                 return 0;
393         }
394         ret = PyRef( PyObject_CallObject( callable.get(), paras.get() ), SAL_NO_ACQUIRE );
395     }
396     catch (::com::sun::star::lang::IllegalArgumentException &e)
397     {
398         raisePyExceptionWithAny( com::sun::star::uno::makeAny( e ) );
399     }
400     catch (::com::sun::star::script::CannotConvertException &e)
401     {
402         raisePyExceptionWithAny( com::sun::star::uno::makeAny( e ) );
403     }
404     catch (::com::sun::star::uno::RuntimeException &e)
405     {
406         raisePyExceptionWithAny( com::sun::star::uno::makeAny( e ) );
407     }
408     catch (::com::sun::star::uno::Exception &e)
409     {
410         raisePyExceptionWithAny( com::sun::star::uno::makeAny( e ) );
411     }
412 
413     return ret.getAcquired();
414 }
415 
416 PyObject *PyUNO_str( PyObject * self )
417 {
418     PyUNO *me = ( PyUNO * ) self;
419 
420     OStringBuffer buf;
421 
422 
423     if( me->members->wrappedObject.getValueType().getTypeClass()
424         == com::sun::star::uno::TypeClass_STRUCT ||
425         me->members->wrappedObject.getValueType().getTypeClass()
426         == com::sun::star::uno::TypeClass_EXCEPTION)
427     {
428         Reference< XMaterialHolder > rHolder(me->members->xInvocation,UNO_QUERY);
429         if( rHolder.is() )
430         {
431             PyThreadDetach antiguard;
432             Any a = rHolder->getMaterial();
433             OUString s = val2str( (void*) a.getValue(), a.getValueType().getTypeLibType() );
434             buf.append( OUStringToOString(s,RTL_TEXTENCODING_ASCII_US) );
435         }
436     }
437     else
438     {
439         // a common UNO object
440         PyThreadDetach antiguard;
441         buf.append( "pyuno object " );
442 
443         OUString s = val2str( (void*)me->members->wrappedObject.getValue(),
444                               me->members->wrappedObject.getValueType().getTypeLibType() );
445         buf.append( OUStringToOString(s,RTL_TEXTENCODING_ASCII_US) );
446     }
447 
448     return PyString_FromString( buf.getStr());
449 }
450 
451 PyObject* PyUNO_getattr (PyObject* self, char* name)
452 {
453     PyUNO* me;
454 
455     try
456     {
457 
458         Runtime runtime;
459 
460         me = (PyUNO*) self;
461         //Handle Python dir () stuff first...
462         if (strcmp (name, "__members__") == 0)
463         {
464             PyObject* member_list;
465             Sequence<OUString> oo_member_list;
466 
467             oo_member_list = me->members->xInvocation->getMemberNames ();
468             member_list = PyList_New (oo_member_list.getLength ());
469             for (int i = 0; i < oo_member_list.getLength (); i++)
470             {
471                 // setitem steals a reference
472                 PyList_SetItem (member_list, i, ustring2PyString(oo_member_list[i]).getAcquired() );
473             }
474             return member_list;
475         }
476 
477         if (strcmp (name, "__dict__") == 0)
478         {
479             Py_INCREF (Py_None);
480             return Py_None;
481         }
482         if (strcmp (name, "__methods__") == 0)
483         {
484             Py_INCREF (Py_None);
485             return Py_None;
486         }
487         if (strcmp (name, "__class__") == 0)
488         {
489             if( me->members->wrappedObject.getValueTypeClass() ==
490                 com::sun::star::uno::TypeClass_STRUCT ||
491                 me->members->wrappedObject.getValueTypeClass() ==
492                 com::sun::star::uno::TypeClass_EXCEPTION )
493             {
494                 return getClass(
495                     me->members->wrappedObject.getValueType().getTypeName(), runtime ).getAcquired();
496             }
497             Py_INCREF (Py_None);
498             return Py_None;
499         }
500 
501         OUString attrName( OUString::createFromAscii( name ) );
502         //We need to find out if it's a method...
503         if (me->members->xInvocation->hasMethod (attrName))
504         {
505             //Create a callable object to invoke this...
506             PyRef ret = PyUNO_callable_new (
507                 me->members->xInvocation,
508                 attrName,
509                 runtime.getImpl()->cargo->xInvocation,
510                 runtime.getImpl()->cargo->xTypeConverter);
511             Py_XINCREF( ret.get() );
512             return ret.get();
513 
514         }
515 
516         //or a property
517         if (me->members->xInvocation->hasProperty ( attrName))
518         {
519             //Return the value of the property
520             Any anyRet;
521             {
522                 PyThreadDetach antiguard;
523                 anyRet = me->members->xInvocation->getValue (attrName);
524             }
525             PyRef ret = runtime.any2PyObject(anyRet);
526             Py_XINCREF( ret.get() );
527             return ret.get();
528         }
529 
530         //or else...
531         PyErr_SetString (PyExc_AttributeError, name);
532     }
533     catch( com::sun::star::reflection::InvocationTargetException & e )
534     {
535         raisePyExceptionWithAny( makeAny(e.TargetException) );
536     }
537     catch( com::sun::star::beans::UnknownPropertyException & e )
538     {
539         raisePyExceptionWithAny( makeAny(e) );
540     }
541     catch( com::sun::star::lang::IllegalArgumentException &e )
542     {
543         raisePyExceptionWithAny( makeAny(e) );
544     }
545     catch( com::sun::star::script::CannotConvertException &e )
546     {
547         raisePyExceptionWithAny( makeAny(e) );
548     }
549     catch( RuntimeException &e )
550     {
551         raisePyExceptionWithAny( makeAny(e) );
552     }
553 
554     return NULL;
555 }
556 
557 int PyUNO_setattr (PyObject* self, char* name, PyObject* value)
558 {
559     PyUNO* me;
560 
561     me = (PyUNO*) self;
562     try
563     {
564         Runtime runtime;
565         Any val= runtime.pyObject2Any(value, ACCEPT_UNO_ANY);
566 
567         OUString attrName( OUString::createFromAscii( name ) );
568         {
569             PyThreadDetach antiguard;
570             if (me->members->xInvocation->hasProperty (attrName))
571             {
572                 me->members->xInvocation->setValue (attrName, val);
573                 return 0; //Keep with Python's boolean system
574             }
575         }
576     }
577     catch( com::sun::star::reflection::InvocationTargetException & e )
578     {
579         raisePyExceptionWithAny( makeAny(e.TargetException) );
580         return 1;
581     }
582     catch( com::sun::star::beans::UnknownPropertyException & e )
583     {
584         raisePyExceptionWithAny( makeAny(e) );
585         return 1;
586     }
587     catch( com::sun::star::script::CannotConvertException &e )
588     {
589         raisePyExceptionWithAny( makeAny(e) );
590         return 1;
591     }
592     catch( RuntimeException & e )
593     {
594         raisePyExceptionWithAny( makeAny( e ) );
595         return 1;
596     }
597     PyErr_SetString (PyExc_AttributeError, name);
598     return 1; //as above.
599 }
600 
601 // ensure object identity and struct equality
602 static int PyUNO_cmp( PyObject *self, PyObject *that )
603 {
604     if( self == that )
605         return 0;
606     int retDefault = self > that ? 1 : -1;
607     try
608     {
609         Runtime runtime;
610         if( PyObject_IsInstance( that, getPyUnoClass( runtime ).get() ) )
611         {
612 
613             PyUNO *me = reinterpret_cast< PyUNO*> ( self );
614             PyUNO *other = reinterpret_cast< PyUNO *> (that );
615             com::sun::star::uno::TypeClass tcMe = me->members->wrappedObject.getValueTypeClass();
616             com::sun::star::uno::TypeClass tcOther = other->members->wrappedObject.getValueTypeClass();
617 
618             if( tcMe == tcOther )
619             {
620                 if( tcMe == com::sun::star::uno::TypeClass_STRUCT ||
621                     tcMe == com::sun::star::uno::TypeClass_EXCEPTION )
622                 {
623                     Reference< XMaterialHolder > xMe( me->members->xInvocation,UNO_QUERY);
624                     Reference< XMaterialHolder > xOther( other->members->xInvocation,UNO_QUERY );
625                     if( xMe->getMaterial() == xOther->getMaterial() )
626                         return 0;
627                 }
628                 else if( tcMe == com::sun::star::uno::TypeClass_INTERFACE )
629                 {
630                     if( me->members->wrappedObject == other->members->wrappedObject )
631 //                     if( me->members->xInvocation == other->members->xInvocation )
632                         return 0;
633                 }
634             }
635         }
636     }
637     catch( com::sun::star::uno::RuntimeException & e)
638     {
639         raisePyExceptionWithAny( makeAny( e ) );
640     }
641     return retDefault;
642 }
643 
644 static PyTypeObject PyUNOType =
645 {
646     PyObject_HEAD_INIT (&PyType_Type)
647     0,
648     const_cast< char * >("pyuno"),
649     sizeof (PyUNO),
650     0,
651     (destructor) PyUNO_del,
652     (printfunc) 0,
653     (getattrfunc) PyUNO_getattr,
654     (setattrfunc) PyUNO_setattr,
655     (cmpfunc) PyUNO_cmp,
656     (reprfunc) PyUNO_repr,
657     0,
658     0,
659     0,
660     (hashfunc) 0,
661     (ternaryfunc) 0,
662     (reprfunc) PyUNO_str,
663     (getattrofunc)0,
664     (setattrofunc)0,
665     NULL,
666     0,
667     NULL,
668     (traverseproc)0,
669     (inquiry)0,
670     (richcmpfunc)0,
671     0,
672     (getiterfunc)0,
673     (iternextfunc)0,
674     NULL,
675     NULL,
676     NULL,
677     NULL,
678     NULL,
679     (descrgetfunc)0,
680     (descrsetfunc)0,
681     0,
682     (initproc)0,
683     (allocfunc)0,
684     (newfunc)0,
685     (freefunc)0,
686     (inquiry)0,
687     NULL,
688     NULL,
689     NULL,
690     NULL,
691     NULL,
692     (destructor)0
693 #if PY_VERSION_HEX >= 0x02060000
694     , 0
695 #endif
696 };
697 
698 PyRef getPyUnoClass( const Runtime &)
699 {
700     return PyRef( reinterpret_cast< PyObject * > ( &PyUNOType ) );
701 }
702 
703 PyObject* PyUNO_new (
704     const Any & targetInterface, const Reference<XSingleServiceFactory> &ssf)
705 {
706     Reference<XInterface> tmp_interface;
707 
708     targetInterface >>= tmp_interface;
709     if (!tmp_interface.is ())
710     {
711         // empty reference !
712         Py_INCREF( Py_None );
713         return Py_None;
714     }
715 
716     return PyUNO_new_UNCHECKED (targetInterface, ssf);
717 }
718 
719 
720 PyObject* PyUNO_new_UNCHECKED (
721     const Any &targetInterface,
722     const Reference<XSingleServiceFactory> &ssf )
723 {
724     PyUNO* self;
725     Sequence<Any> arguments (1);
726     Reference<XInterface> tmp_interface;
727 
728     self = PyObject_New (PyUNO, &PyUNOType);
729     if (self == NULL)
730         return NULL; //NULL == error
731     self->members = new PyUNOInternals();
732 
733     arguments[0] <<= targetInterface;
734     {
735         PyThreadDetach antiguard;
736         tmp_interface = ssf->createInstanceWithArguments (arguments);
737         Reference<XInvocation2> tmp_invocation (tmp_interface, UNO_QUERY);
738         self->members->xInvocation = tmp_invocation;
739         self->members->wrappedObject = targetInterface;
740     }
741     return (PyObject*) self;
742 }
743 
744 }
745