xref: /trunk/main/pyuno/source/module/pyuno.cxx (revision d1c4de67)
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 <rtl/strbuf.hxx>
27 #include <rtl/ustrbuf.hxx>
28 
29 #include <osl/thread.h>
30 
31 #include <com/sun/star/lang/XServiceInfo.hpp>
32 #include <com/sun/star/lang/XTypeProvider.hpp>
33 #include <com/sun/star/beans/XPropertySet.hpp>
34 #include <com/sun/star/beans/XMaterialHolder.hpp>
35 
36 #define TO_ASCII(x) OUStringToOString( x , RTL_TEXTENCODING_ASCII_US).getStr()
37 
38 using rtl::OStringBuffer;
39 using rtl::OUStringBuffer;
40 using rtl::OUStringToOString;
41 using rtl::OUString;
42 using com::sun::star::uno::Sequence;
43 using com::sun::star::uno::Reference;
44 using com::sun::star::uno::XInterface;
45 using com::sun::star::uno::Any;
46 using com::sun::star::uno::makeAny;
47 using com::sun::star::uno::UNO_QUERY;
48 using com::sun::star::uno::Type;
49 using com::sun::star::uno::TypeClass;
50 using com::sun::star::uno::RuntimeException;
51 using com::sun::star::uno::Exception;
52 using com::sun::star::uno::XComponentContext;
53 using com::sun::star::lang::XSingleServiceFactory;
54 using com::sun::star::lang::XServiceInfo;
55 using com::sun::star::lang::XTypeProvider;
56 using com::sun::star::script::XTypeConverter;
57 using com::sun::star::script::XInvocation2;
58 using com::sun::star::beans::XMaterialHolder;
59 
60 namespace pyuno
61 {
62 
63 PyObject *PyUNO_str( PyObject * self );
64 
PyUNO_del(PyObject * self)65 void PyUNO_del (PyObject* self)
66 {
67     PyUNO* me = reinterpret_cast< PyUNO* > (self);
68     {
69         PyThreadDetach antiguard;
70         delete me->members;
71     }
72     PyObject_Del (self);
73 }
74 
75 
76 
val2str(const void * pVal,typelib_TypeDescriptionReference * pTypeRef,sal_Int32 mode)77 OUString val2str( const void * pVal, typelib_TypeDescriptionReference * pTypeRef , sal_Int32 mode ) SAL_THROW( () )
78 {
79 	OSL_ASSERT( pVal );
80 	if (pTypeRef->eTypeClass == typelib_TypeClass_VOID)
81 		return OUString( RTL_CONSTASCII_USTRINGPARAM("void") );
82 
83 	OUStringBuffer buf( 64 );
84 	buf.append( (sal_Unicode)'(' );
85 	buf.append( pTypeRef->pTypeName );
86 	buf.append( (sal_Unicode)')' );
87 
88 	switch (pTypeRef->eTypeClass)
89 	{
90 	case typelib_TypeClass_INTERFACE:
91     {
92 		buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") );
93 		buf.append( reinterpret_cast< sal_IntPtr >(*(void **)pVal), 16 );
94         if( VAL2STR_MODE_DEEP == mode )
95         {
96             buf.appendAscii( "{" );        Reference< XInterface > r = *( Reference< XInterface > * ) pVal;
97             Reference< XServiceInfo > serviceInfo( r, UNO_QUERY);
98             Reference< XTypeProvider > typeProvider(r,UNO_QUERY);
99             if( serviceInfo.is() )
100             {
101                 buf.appendAscii("implementationName=" );
102                 buf.append(serviceInfo->getImplementationName() );
103                 buf.appendAscii(", supportedServices={" );
104                 Sequence< OUString > seq = serviceInfo->getSupportedServiceNames();
105                 for( int i = 0 ; i < seq.getLength() ; i ++ )
106                 {
107                     buf.append( seq[i] );
108                     if( i +1 != seq.getLength() )
109                         buf.appendAscii( "," );
110                 }
111                 buf.appendAscii("}");
112             }
113 
114             if( typeProvider.is() )
115             {
116                 buf.appendAscii(", supportedInterfaces={" );
117                 Sequence< Type > seq (typeProvider->getTypes());
118                 for( int i = 0 ; i < seq.getLength() ; i ++ )
119                 {
120                     buf.append(seq[i].getTypeName());
121                     if( i +1 != seq.getLength() )
122                         buf.appendAscii( "," );
123                 }
124                 buf.appendAscii("}");
125             }
126             buf.appendAscii( "}" );
127         }
128 
129 		break;
130     }
131 	case typelib_TypeClass_UNION:
132 	{
133 //  		typelib_TypeDescription * pTypeDescr = 0;
134 //  		TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
135 //  		buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{ ") );
136 //  		buf.append( val2str( (char *)pVal + ((typelib_UnionTypeDescription *)pTypeDescr)->nValueOffset,
137 //  							 union_getSetType( pVal, pTypeDescr ) ) );
138 //  		buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" }") );
139 //  		TYPELIB_DANGER_RELEASE( pTypeDescr );
140 		break;
141 	}
142 	case typelib_TypeClass_STRUCT:
143 	case typelib_TypeClass_EXCEPTION:
144 	{
145 		buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{ ") );
146 		typelib_TypeDescription * pTypeDescr = 0;
147 		TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
148 		OSL_ASSERT( pTypeDescr );
149 
150 		typelib_CompoundTypeDescription * pCompType = (typelib_CompoundTypeDescription *)pTypeDescr;
151 		sal_Int32 nDescr = pCompType->nMembers;
152 
153 		if (pCompType->pBaseTypeDescription)
154 		{
155 			buf.append( val2str( pVal, ((typelib_TypeDescription *)pCompType->pBaseTypeDescription)->pWeakRef,mode ) );
156 			if (nDescr)
157 				buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", ") );
158 		}
159 
160 		typelib_TypeDescriptionReference ** ppTypeRefs = pCompType->ppTypeRefs;
161 		sal_Int32 * pMemberOffsets = pCompType->pMemberOffsets;
162 		rtl_uString ** ppMemberNames = pCompType->ppMemberNames;
163 
164 		for ( sal_Int32 nPos = 0; nPos < nDescr; ++nPos )
165 		{
166 			buf.append( ppMemberNames[nPos] );
167 			buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" = ") );
168 			typelib_TypeDescription * pMemberType = 0;
169 			TYPELIB_DANGER_GET( &pMemberType, ppTypeRefs[nPos] );
170 			buf.append( val2str( (char *)pVal + pMemberOffsets[nPos], pMemberType->pWeakRef, mode ) );
171 			TYPELIB_DANGER_RELEASE( pMemberType );
172 			if (nPos < (nDescr -1))
173 				buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", ") );
174 		}
175 
176 		TYPELIB_DANGER_RELEASE( pTypeDescr );
177 
178 		buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" }") );
179 		break;
180 	}
181 	case typelib_TypeClass_SEQUENCE:
182 	{
183 		typelib_TypeDescription * pTypeDescr = 0;
184 		TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
185 
186 		uno_Sequence * pSequence = *(uno_Sequence **)pVal;
187 		typelib_TypeDescription * pElementTypeDescr = 0;
188 		TYPELIB_DANGER_GET( &pElementTypeDescr, ((typelib_IndirectTypeDescription *)pTypeDescr)->pType );
189 
190 		sal_Int32 nElementSize = pElementTypeDescr->nSize;
191 		sal_Int32 nElements	   = pSequence->nElements;
192 
193 		if (nElements)
194 		{
195 			buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{ ") );
196 			char * pElements = pSequence->elements;
197 			for ( sal_Int32 nPos = 0; nPos < nElements; ++nPos )
198 			{
199 				buf.append( val2str( pElements + (nElementSize * nPos), pElementTypeDescr->pWeakRef, mode ) );
200 				if (nPos < (nElements -1))
201 					buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(", ") );
202 			}
203 			buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" }") );
204 		}
205 		else
206 		{
207 			buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{}") );
208 		}
209 		TYPELIB_DANGER_RELEASE( pElementTypeDescr );
210 		TYPELIB_DANGER_RELEASE( pTypeDescr );
211 		break;
212 	}
213 	case typelib_TypeClass_ANY:
214 		buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("{ ") );
215 		buf.append( val2str( ((uno_Any *)pVal)->pData,
216 							 ((uno_Any *)pVal)->pType ,
217                              mode) );
218 		buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" }") );
219 		break;
220 	case typelib_TypeClass_TYPE:
221 		buf.append( (*(typelib_TypeDescriptionReference **)pVal)->pTypeName );
222 		break;
223 	case typelib_TypeClass_STRING:
224 		buf.append( (sal_Unicode)'\"' );
225 		buf.append( *(rtl_uString **)pVal );
226 		buf.append( (sal_Unicode)'\"' );
227 		break;
228 	case typelib_TypeClass_ENUM:
229 	{
230 		typelib_TypeDescription * pTypeDescr = 0;
231 		TYPELIB_DANGER_GET( &pTypeDescr, pTypeRef );
232 
233 		sal_Int32 * pValues = ((typelib_EnumTypeDescription *)pTypeDescr)->pEnumValues;
234 		sal_Int32 nPos = ((typelib_EnumTypeDescription *)pTypeDescr)->nEnumValues;
235 		while (nPos--)
236 		{
237 			if (pValues[nPos] == *(int *)pVal)
238 				break;
239 		}
240 		if (nPos >= 0)
241 			buf.append( ((typelib_EnumTypeDescription *)pTypeDescr)->ppEnumNames[nPos] );
242 		else
243 			buf.append( (sal_Unicode)'?' );
244 
245 		TYPELIB_DANGER_RELEASE( pTypeDescr );
246 		break;
247 	}
248 	case typelib_TypeClass_BOOLEAN:
249 		if (*(sal_Bool *)pVal)
250 			buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("true") );
251 		else
252 			buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("false") );
253 		break;
254 	case typelib_TypeClass_CHAR:
255 		buf.append( (sal_Unicode)'\'' );
256 		buf.append( *(sal_Unicode *)pVal );
257 		buf.append( (sal_Unicode)'\'' );
258 		break;
259 	case typelib_TypeClass_FLOAT:
260 		buf.append( *(float *)pVal );
261 		break;
262 	case typelib_TypeClass_DOUBLE:
263 		buf.append( *(double *)pVal );
264 		break;
265 	case typelib_TypeClass_BYTE:
266 		buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") );
267 		buf.append( (sal_Int32)*(sal_Int8 *)pVal, 16 );
268 		break;
269 	case typelib_TypeClass_SHORT:
270 		buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") );
271 		buf.append( (sal_Int32)*(sal_Int16 *)pVal, 16 );
272 		break;
273 	case typelib_TypeClass_UNSIGNED_SHORT:
274 		buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") );
275 		buf.append( (sal_Int32)*(sal_uInt16 *)pVal, 16 );
276 		break;
277 	case typelib_TypeClass_LONG:
278 		buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") );
279 		buf.append( *(sal_Int32 *)pVal, 16 );
280 		break;
281 	case typelib_TypeClass_UNSIGNED_LONG:
282 		buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") );
283 		buf.append( (sal_Int64)*(sal_uInt32 *)pVal, 16 );
284 		break;
285 	case typelib_TypeClass_HYPER:
286 	case typelib_TypeClass_UNSIGNED_HYPER:
287 		buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("0x") );
288 #if defined(GCC) && defined(SPARC)
289 		{
290 			sal_Int64 aVal;
291 			*(sal_Int32 *)&aVal = *(sal_Int32 *)pVal;
292 			*((sal_Int32 *)&aVal +1)= *((sal_Int32 *)pVal +1);
293 			buf.append( aVal, 16 );
294 		}
295 #else
296 		buf.append( *(sal_Int64 *)pVal, 16 );
297 #endif
298 		break;
299 
300 	case typelib_TypeClass_VOID:
301 	case typelib_TypeClass_ARRAY:
302 	case typelib_TypeClass_UNKNOWN:
303 	case typelib_TypeClass_SERVICE:
304 	case typelib_TypeClass_MODULE:
305 	default:
306 		buf.append( (sal_Unicode)'?' );
307 	}
308 
309 	return buf.makeStringAndClear();
310 }
311 
312 
PyUNO_repr(PyObject * self)313 PyObject *PyUNO_repr( PyObject  * self )
314 {
315     PyUNO *me = (PyUNO * ) self;
316     PyObject * ret = 0;
317 
318     if( me->members->wrappedObject.getValueType().getTypeClass()
319         == com::sun::star::uno::TypeClass_EXCEPTION )
320     {
321         Reference< XMaterialHolder > rHolder(me->members->xInvocation,UNO_QUERY);
322         if( rHolder.is() )
323         {
324             Any a = rHolder->getMaterial();
325             Exception e;
326             a >>= e;
327             ret = ustring2PyUnicode(e.Message ).getAcquired();
328         }
329     }
330     else
331     {
332         ret = PyUNO_str( self );
333     }
334     return ret;
335 }
336 
PyUNO_invoke(PyObject * object,const char * name,PyObject * args)337 PyObject *PyUNO_invoke( PyObject *object, const char *name , PyObject *args )
338 {
339     PyRef ret;
340     try
341     {
342         Runtime runtime;
343 
344         PyRef paras,callable;
345         if( PyObject_IsInstance( object, getPyUnoClass().get() ) )
346         {
347             PyUNO* me = (PyUNO*) object;
348             OUString attrName = OUString::createFromAscii(name);
349             if (! me->members->xInvocation->hasMethod (attrName))
350             {
351                 OUStringBuffer buf;
352                 buf.appendAscii( "Attribute " );
353                 buf.append( attrName );
354                 buf.appendAscii( " unknown" );
355                 throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface > () );
356             }
357             callable = PyUNO_callable_new (
358                 me->members->xInvocation,
359                 attrName,
360                 ACCEPT_UNO_ANY);
361             paras = args;
362         }
363         else
364         {
365             // clean the tuple from uno.Any !
366             int size = PyTuple_Size( args );
367             { // for CC, keeping ref-count of tuple being 1
368             paras = PyRef(PyTuple_New( size ), SAL_NO_ACQUIRE);
369             }
370             for( int i = 0 ; i < size ;i ++ )
371             {
372                 PyObject * element = PyTuple_GetItem( args , i );
373                 if( PyObject_IsInstance( element , getAnyClass( runtime ).get() ) )
374                 {
375                     element = PyObject_GetAttrString(
376                         element, const_cast< char * >("value") );
377                 }
378                 else
379                 {
380                     Py_XINCREF( element );
381                 }
382                 PyTuple_SetItem( paras.get(), i , element );
383             }
384             callable = PyRef( PyObject_GetAttrString( object , (char*)name ), SAL_NO_ACQUIRE );
385             if( !callable.is() )
386                 return 0;
387         }
388         ret = PyRef( PyObject_CallObject( callable.get(), paras.get() ), SAL_NO_ACQUIRE );
389     }
390     catch (::com::sun::star::lang::IllegalArgumentException &e)
391     {
392         raisePyExceptionWithAny( com::sun::star::uno::makeAny( e ) );
393     }
394     catch (::com::sun::star::script::CannotConvertException &e)
395     {
396         raisePyExceptionWithAny( com::sun::star::uno::makeAny( e ) );
397     }
398     catch (::com::sun::star::uno::RuntimeException &e)
399     {
400         raisePyExceptionWithAny( com::sun::star::uno::makeAny( e ) );
401     }
402     catch (::com::sun::star::uno::Exception &e)
403     {
404         raisePyExceptionWithAny( com::sun::star::uno::makeAny( e ) );
405     }
406 
407     return ret.getAcquired();
408 }
409 
PyUNO_str(PyObject * self)410 PyObject *PyUNO_str( PyObject * self )
411 {
412     PyUNO *me = ( PyUNO * ) self;
413 
414     OStringBuffer buf;
415 
416 
417     if( me->members->wrappedObject.getValueType().getTypeClass()
418         == com::sun::star::uno::TypeClass_STRUCT ||
419         me->members->wrappedObject.getValueType().getTypeClass()
420         == com::sun::star::uno::TypeClass_EXCEPTION)
421     {
422         Reference< XMaterialHolder > rHolder(me->members->xInvocation,UNO_QUERY);
423         if( rHolder.is() )
424         {
425             PyThreadDetach antiguard;
426             Any a = rHolder->getMaterial();
427             OUString s = val2str( (void*) a.getValue(), a.getValueType().getTypeLibType() );
428             buf.append( OUStringToOString(s,RTL_TEXTENCODING_ASCII_US) );
429         }
430     }
431     else
432     {
433         // a common UNO object
434         PyThreadDetach antiguard;
435         buf.append( "pyuno object " );
436 
437         OUString s = val2str( (void*)me->members->wrappedObject.getValue(),
438                               me->members->wrappedObject.getValueType().getTypeLibType() );
439         buf.append( OUStringToOString(s,RTL_TEXTENCODING_ASCII_US) );
440     }
441 
442     return PYSTR_FROMSTR( buf.getStr() );
443 }
444 
445 #if PY_MAJOR_VERSION >= 3
PyUNO_getattr(PyObject * self,PyObject * attr_name)446 PyObject* PyUNO_getattr (PyObject* self, PyObject* attr_name)
447 #else
448 PyObject* PyUNO_getattr (PyObject* self, char* name)
449 #endif
450 {
451     PyUNO* me;
452 
453 #if PY_VERSION_HEX >= 0x03030000 && PY_VERSION_HEX < 0x03060000
454     char *name = PyUnicode_AsUTF8(attr_name);
455 #elif PY_MAJOR_VERSION >= 3
456     PyRef pUtf8(PyUnicode_AsUTF8String(attr_name), SAL_NO_ACQUIRE);
457     char *name = PyBytes_AsString(pUtf8.get());
458 #endif
459     try
460     {
461 
462         Runtime runtime;
463 
464         me = (PyUNO*) self;
465 #if PY_MAJOR_VERSION < 3
466         //Handle Python dir () stuff first...
467         if (strcmp (name, "__members__") == 0)
468         {
469             PyObject* member_list;
470             Sequence<OUString> oo_member_list;
471 
472             oo_member_list = me->members->xInvocation->getMemberNames ();
473             member_list = PyList_New (oo_member_list.getLength ());
474             for (int i = 0; i < oo_member_list.getLength (); i++)
475             {
476                 // setitem steals a reference
477                 PyList_SetItem (member_list, i, ustring2PyString(oo_member_list[i]).getAcquired() );
478             }
479             return member_list;
480         }
481 #endif
482 
483         if (strcmp (name, "__dict__") == 0)
484         {
485             Py_INCREF (Py_None);
486             return Py_None;
487         }
488 #if PY_MAJOR_VERSION < 3
489         if (strcmp (name, "__methods__") == 0)
490         {
491             Py_INCREF (Py_None);
492             return Py_None;
493         }
494 #endif
495         if (strcmp (name, "__class__") == 0)
496         {
497             if( me->members->wrappedObject.getValueTypeClass() ==
498                 com::sun::star::uno::TypeClass_STRUCT ||
499                 me->members->wrappedObject.getValueTypeClass() ==
500                 com::sun::star::uno::TypeClass_EXCEPTION )
501             {
502                 return getClass(
503                     me->members->wrappedObject.getValueType().getTypeName(), runtime ).getAcquired();
504             }
505             Py_INCREF (Py_None);
506             return Py_None;
507         }
508 
509         OUString attrName( OUString::createFromAscii( name ) );
510         //We need to find out if it's a method...
511         if (me->members->xInvocation->hasMethod (attrName))
512         {
513             //Create a callable object to invoke this...
514             PyRef ret = PyUNO_callable_new (
515                 me->members->xInvocation,
516                 attrName);
517             Py_XINCREF( ret.get() );
518             return ret.get();
519 
520         }
521 
522         //or a property
523         if (me->members->xInvocation->hasProperty ( attrName))
524         {
525             //Return the value of the property
526             Any anyRet;
527             {
528                 PyThreadDetach antiguard;
529                 anyRet = me->members->xInvocation->getValue (attrName);
530             }
531             PyRef ret = runtime.any2PyObject(anyRet);
532             Py_XINCREF( ret.get() );
533             return ret.get();
534         }
535 
536         //or else...
537         PyErr_SetString (PyExc_AttributeError, name);
538     }
539     catch( com::sun::star::reflection::InvocationTargetException & e )
540     {
541         raisePyExceptionWithAny( makeAny(e.TargetException) );
542     }
543     catch( com::sun::star::beans::UnknownPropertyException & e )
544     {
545         raisePyExceptionWithAny( makeAny(e) );
546     }
547     catch( com::sun::star::lang::IllegalArgumentException &e )
548     {
549         raisePyExceptionWithAny( makeAny(e) );
550     }
551     catch( com::sun::star::script::CannotConvertException &e )
552     {
553         raisePyExceptionWithAny( makeAny(e) );
554     }
555     catch( RuntimeException &e )
556     {
557         raisePyExceptionWithAny( makeAny(e) );
558     }
559 
560     return NULL;
561 }
562 
563 #if PY_MAJOR_VERSION >= 3
PyUNO_setattr(PyObject * self,PyObject * attr_name,PyObject * value)564 int PyUNO_setattr (PyObject* self, PyObject* attr_name, PyObject* value)
565 #else
566 int PyUNO_setattr (PyObject* self, char* name, PyObject* value)
567 #endif
568 {
569     PyUNO* me;
570 
571 #if PY_VERSION_HEX >= 0x03030000 && PY_VERSION_HEX < 0x03060000
572     char *name = PyUnicode_AsUTF8(attr_name);
573 #elif PY_MAJOR_VERSION >= 3
574     PyRef pUtf8(PyUnicode_AsUTF8String(attr_name), SAL_NO_ACQUIRE);
575     char *name = PyBytes_AsString(pUtf8.get());
576 #endif
577     me = (PyUNO*) self;
578     try
579     {
580         Runtime runtime;
581         Any val= runtime.pyObject2Any(value, ACCEPT_UNO_ANY);
582 
583         OUString attrName( OUString::createFromAscii( name ) );
584         {
585             PyThreadDetach antiguard;
586             if (me->members->xInvocation->hasProperty (attrName))
587             {
588                 me->members->xInvocation->setValue (attrName, val);
589                 return 0; //Keep with Python's boolean system
590             }
591         }
592     }
593     catch( com::sun::star::reflection::InvocationTargetException & e )
594     {
595         raisePyExceptionWithAny( makeAny(e.TargetException) );
596         return 1;
597     }
598     catch( com::sun::star::beans::UnknownPropertyException & e )
599     {
600         raisePyExceptionWithAny( makeAny(e) );
601         return 1;
602     }
603     catch( com::sun::star::script::CannotConvertException &e )
604     {
605         raisePyExceptionWithAny( makeAny(e) );
606         return 1;
607     }
608     catch( RuntimeException & e )
609     {
610         raisePyExceptionWithAny( makeAny( e ) );
611         return 1;
612     }
613     PyErr_SetString (PyExc_AttributeError, name);
614     return 1; //as above.
615 }
616 
617 #if PY_MAJOR_VERSION >= 3
PyUNO_dir(PyObject * self,PyObject * that)618 static PyObject *PyUNO_dir( PyObject *self, PyObject *that )
619 {
620     PyUNO* me;
621     PyObject* member_list;
622     Sequence<OUString> oo_member_list;
623 
624     me = (PyUNO*) self;
625     oo_member_list = me->members->xInvocation->getMemberNames ();
626     member_list = PyList_New (oo_member_list.getLength ());
627     for (int i = 0; i < oo_member_list.getLength (); i++)
628     {
629         // setitem steals a reference
630         PyList_SetItem (member_list, i, ustring2PyUnicode(oo_member_list[i]).getAcquired() );
631     }
632     return member_list;
633 }
634 
PyUNO_richcompare(PyObject * self,PyObject * that,int op)635 static PyObject *PyUNO_richcompare( PyObject *self, PyObject *that, int op )
636 {
637     switch (op)
638     {
639     case Py_EQ:
640     case Py_NE:
641         if( self == that )
642         {
643             if (op == Py_EQ)
644                 Py_RETURN_TRUE;
645             else
646                 Py_RETURN_FALSE;
647         }
648         try
649         {
650             Runtime runtime;
651             if( PyObject_IsInstance( that, getPyUnoClass().get() ) )
652             {
653                 PyUNO *me = reinterpret_cast< PyUNO*> ( self );
654                 PyUNO *other = reinterpret_cast< PyUNO *> (that );
655                 com::sun::star::uno::TypeClass tcMe = me->members->wrappedObject.getValueTypeClass();
656                 com::sun::star::uno::TypeClass tcOther = other->members->wrappedObject.getValueTypeClass();
657 
658                 if( tcMe == tcOther )
659                 {
660                     if( tcMe == com::sun::star::uno::TypeClass_STRUCT ||
661                         tcMe == com::sun::star::uno::TypeClass_EXCEPTION )
662                     {
663                         Reference< XMaterialHolder > xMe( me->members->xInvocation,UNO_QUERY);
664                         Reference< XMaterialHolder > xOther( other->members->xInvocation,UNO_QUERY );
665                         if( xMe->getMaterial() == xOther->getMaterial() )
666                         {
667                             if (op == Py_EQ)
668                                 Py_RETURN_TRUE;
669                             else
670                                 Py_RETURN_FALSE;
671                         }
672                     }
673                     else if( tcMe == com::sun::star::uno::TypeClass_INTERFACE )
674                     {
675                         if( me->members->wrappedObject == other->members->wrappedObject )
676                         {
677                             if (op == Py_EQ)
678                                 Py_RETURN_TRUE;
679                             else
680                                 Py_RETURN_FALSE;
681                         }
682                     }
683                 }
684             }
685             if (op == Py_EQ)
686                 Py_RETURN_FALSE;
687             else
688                 Py_RETURN_TRUE;
689         }
690         catch( com::sun::star::uno::RuntimeException & e)
691         {
692             raisePyExceptionWithAny( makeAny( e ) );
693         }
694         break;
695     default:
696         PyErr_SetString(Py_NotImplemented, "not implemented");
697         break;
698     }
699 
700     return NULL;
701 }
702 
703 
704 static struct PyMethodDef PyUNO_methods[] = {
705     { "__dir__", (PyCFunction)PyUNO_dir, METH_VARARGS, NULL},
706     { NULL, NULL }
707 };
708 
709 #else
710 // ensure object identity and struct equality
PyUNO_cmp(PyObject * self,PyObject * that)711 static int PyUNO_cmp( PyObject *self, PyObject *that )
712 {
713     if( self == that )
714         return 0;
715     int retDefault = self > that ? 1 : -1;
716     try
717     {
718         Runtime runtime;
719         if( PyObject_IsInstance( that, getPyUnoClass().get() ) )
720         {
721 
722             PyUNO *me = reinterpret_cast< PyUNO*> ( self );
723             PyUNO *other = reinterpret_cast< PyUNO *> (that );
724             com::sun::star::uno::TypeClass tcMe = me->members->wrappedObject.getValueTypeClass();
725             com::sun::star::uno::TypeClass tcOther = other->members->wrappedObject.getValueTypeClass();
726 
727             if( tcMe == tcOther )
728             {
729                 if( tcMe == com::sun::star::uno::TypeClass_STRUCT ||
730                     tcMe == com::sun::star::uno::TypeClass_EXCEPTION )
731                 {
732                     Reference< XMaterialHolder > xMe( me->members->xInvocation,UNO_QUERY);
733                     Reference< XMaterialHolder > xOther( other->members->xInvocation,UNO_QUERY );
734                     if( xMe->getMaterial() == xOther->getMaterial() )
735                         return 0;
736                 }
737                 else if( tcMe == com::sun::star::uno::TypeClass_INTERFACE )
738                 {
739                     if( me->members->wrappedObject == other->members->wrappedObject )
740 //                     if( me->members->xInvocation == other->members->xInvocation )
741                         return 0;
742                 }
743             }
744         }
745     }
746     catch( com::sun::star::uno::RuntimeException & e)
747     {
748         raisePyExceptionWithAny( makeAny( e ) );
749     }
750     return retDefault;
751 }
752 #endif
753 
754 static PyTypeObject PyUNOType =
755 {
756     PyVarObject_HEAD_INIT(&PyType_Type, 0)
757     const_cast< char * >("pyuno"),
758     sizeof (PyUNO),
759     0,
760     (destructor) PyUNO_del,
761     (printfunc) 0,
762 #if PY_MAJOR_VERSION >= 3
763     (getattrfunc) 0,
764     (setattrfunc) 0,
765     0,
766 #else
767     (getattrfunc) PyUNO_getattr, /* tp_getattr */
768     (setattrfunc) PyUNO_setattr, /* tp_setattr */
769     (cmpfunc) PyUNO_cmp,
770 #endif
771     (reprfunc) PyUNO_repr,
772     0,
773     0,
774     0,
775     (hashfunc) 0,
776     (ternaryfunc) 0,
777     (reprfunc) PyUNO_str,
778 #if PY_MAJOR_VERSION >= 3
779     (getattrofunc)PyUNO_getattr, /* tp_getattro */
780     (setattrofunc)PyUNO_setattr, /* tp_setattro */
781 #else
782     (getattrofunc)0,
783     (setattrofunc)0,
784 #endif
785     NULL,
786     0,
787     NULL,
788     (traverseproc)0,
789     (inquiry)0,
790 #if PY_MAJOR_VERSION >= 3
791     PyUNO_richcompare, /* tp_richcompare */
792 #else
793     (richcmpfunc)0,
794 #endif
795     0,
796     (getiterfunc)0,
797     (iternextfunc)0,
798 #if PY_MAJOR_VERSION >= 3
799     PyUNO_methods, /* tp_methods */
800 #else
801     NULL,
802 #endif
803     NULL,
804     NULL,
805     NULL,
806     NULL,
807     (descrgetfunc)0,
808     (descrsetfunc)0,
809     0,
810     (initproc)0,
811     (allocfunc)0,
812     (newfunc)0,
813     (freefunc)0,
814     (inquiry)0,
815     NULL,
816     NULL,
817     NULL,
818     NULL,
819     NULL,
820     (destructor)0
821 #if PY_VERSION_HEX >= 0x02060000 && PY_VERSION_HEX < 0x03060000
822     , 0
823 #endif
824 };
825 
getPyUnoClass()826 PyRef getPyUnoClass()
827 {
828     return PyRef( reinterpret_cast< PyObject * > ( &PyUNOType ) );
829 }
830 
PyUNO_new(const Any & targetInterface,const Reference<XSingleServiceFactory> & ssf)831 PyObject* PyUNO_new (
832     const Any & targetInterface, const Reference<XSingleServiceFactory> &ssf)
833 {
834     Reference<XInterface> tmp_interface;
835 
836     targetInterface >>= tmp_interface;
837     if (!tmp_interface.is ())
838     {
839         // empty reference !
840         Py_INCREF( Py_None );
841         return Py_None;
842     }
843 
844     return PyUNO_new_UNCHECKED (targetInterface, ssf);
845 }
846 
847 
PyUNO_new_UNCHECKED(const Any & targetInterface,const Reference<XSingleServiceFactory> & ssf)848 PyObject* PyUNO_new_UNCHECKED (
849     const Any &targetInterface,
850     const Reference<XSingleServiceFactory> &ssf )
851 {
852     PyUNO* self;
853     Sequence<Any> arguments (1);
854     Reference<XInterface> tmp_interface;
855 
856     self = PyObject_New (PyUNO, &PyUNOType);
857     if (self == NULL)
858         return NULL; //NULL == error
859     self->members = new PyUNOInternals();
860 
861     arguments[0] <<= targetInterface;
862     {
863         PyThreadDetach antiguard;
864         tmp_interface = ssf->createInstanceWithArguments (arguments);
865         Reference<XInvocation2> tmp_invocation (tmp_interface, UNO_QUERY);
866         self->members->xInvocation = tmp_invocation;
867         self->members->wrappedObject = targetInterface;
868     }
869     return (PyObject*) self;
870 }
871 
872 }
873