1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "pyuno_impl.hxx"
22 #include <rtl/strbuf.hxx>
23 #include <rtl/ustrbuf.hxx>
25 #include <osl/thread.h>
27 #include <com/sun/star/lang/XServiceInfo.hpp>
28 #include <com/sun/star/lang/XTypeProvider.hpp>
29 #include <com/sun/star/beans/XPropertySet.hpp>
30 #include <com/sun/star/beans/XMaterialHolder.hpp>
32 using com::sun::star::uno::Sequence
;
33 using com::sun::star::uno::Reference
;
34 using com::sun::star::uno::XInterface
;
35 using com::sun::star::uno::Any
;
36 using com::sun::star::uno::makeAny
;
37 using com::sun::star::uno::UNO_QUERY
;
38 using com::sun::star::uno::Type
;
39 using com::sun::star::uno::TypeClass
;
40 using com::sun::star::uno::RuntimeException
;
41 using com::sun::star::uno::Exception
;
42 using com::sun::star::uno::XComponentContext
;
43 using com::sun::star::lang::XSingleServiceFactory
;
44 using com::sun::star::lang::XServiceInfo
;
45 using com::sun::star::lang::XTypeProvider
;
46 using com::sun::star::script::XTypeConverter
;
47 using com::sun::star::script::XInvocation2
;
48 using com::sun::star::beans::XMaterialHolder
;
53 PyObject
*PyUNO_str( PyObject
* self
);
55 void PyUNO_del (PyObject
* self
)
57 PyUNO
* me
= reinterpret_cast< PyUNO
* > (self
);
59 PyThreadDetach antiguard
;
67 OUString
val2str( const void * pVal
, typelib_TypeDescriptionReference
* pTypeRef
, sal_Int32 mode
) SAL_THROW(())
70 if (pTypeRef
->eTypeClass
== typelib_TypeClass_VOID
)
71 return OUString("void");
73 OUStringBuffer
buf( 64 );
74 buf
.append( (sal_Unicode
)'(' );
75 buf
.append( pTypeRef
->pTypeName
);
76 buf
.append( (sal_Unicode
)')' );
78 switch (pTypeRef
->eTypeClass
)
80 case typelib_TypeClass_INTERFACE
:
83 buf
.append( reinterpret_cast< sal_IntPtr
>(*(void **)pVal
), 16 );
84 if( VAL2STR_MODE_DEEP
== mode
)
86 buf
.append( "{" ); Reference
< XInterface
> r
= *( Reference
< XInterface
> * ) pVal
;
87 Reference
< XServiceInfo
> serviceInfo( r
, UNO_QUERY
);
88 Reference
< XTypeProvider
> typeProvider(r
,UNO_QUERY
);
89 if( serviceInfo
.is() )
91 buf
.append("implementationName=" );
92 buf
.append(serviceInfo
->getImplementationName() );
93 buf
.append(", supportedServices={" );
94 Sequence
< OUString
> seq
= serviceInfo
->getSupportedServiceNames();
95 for( int i
= 0 ; i
< seq
.getLength() ; i
++ )
98 if( i
+1 != seq
.getLength() )
104 if( typeProvider
.is() )
106 buf
.append(", supportedInterfaces={" );
107 Sequence
< Type
> seq (typeProvider
->getTypes());
108 for( int i
= 0 ; i
< seq
.getLength() ; i
++ )
110 buf
.append(seq
[i
].getTypeName());
111 if( i
+1 != seq
.getLength() )
121 case typelib_TypeClass_UNION
:
125 case typelib_TypeClass_STRUCT
:
126 case typelib_TypeClass_EXCEPTION
:
129 typelib_TypeDescription
* pTypeDescr
= 0;
130 TYPELIB_DANGER_GET( &pTypeDescr
, pTypeRef
);
131 OSL_ASSERT( pTypeDescr
);
133 typelib_CompoundTypeDescription
* pCompType
= (typelib_CompoundTypeDescription
*)pTypeDescr
;
134 sal_Int32 nDescr
= pCompType
->nMembers
;
136 if (pCompType
->pBaseTypeDescription
)
138 buf
.append( val2str( pVal
, ((typelib_TypeDescription
*)pCompType
->pBaseTypeDescription
)->pWeakRef
,mode
) );
143 typelib_TypeDescriptionReference
** ppTypeRefs
= pCompType
->ppTypeRefs
;
144 sal_Int32
* pMemberOffsets
= pCompType
->pMemberOffsets
;
145 rtl_uString
** ppMemberNames
= pCompType
->ppMemberNames
;
147 for ( sal_Int32 nPos
= 0; nPos
< nDescr
; ++nPos
)
149 buf
.append( ppMemberNames
[nPos
] );
151 typelib_TypeDescription
* pMemberType
= 0;
152 TYPELIB_DANGER_GET( &pMemberType
, ppTypeRefs
[nPos
] );
153 buf
.append( val2str( (char *)pVal
+ pMemberOffsets
[nPos
], pMemberType
->pWeakRef
, mode
) );
154 TYPELIB_DANGER_RELEASE( pMemberType
);
155 if (nPos
< (nDescr
-1))
159 TYPELIB_DANGER_RELEASE( pTypeDescr
);
164 case typelib_TypeClass_SEQUENCE
:
166 typelib_TypeDescription
* pTypeDescr
= 0;
167 TYPELIB_DANGER_GET( &pTypeDescr
, pTypeRef
);
169 uno_Sequence
* pSequence
= *(uno_Sequence
**)pVal
;
170 typelib_TypeDescription
* pElementTypeDescr
= 0;
171 TYPELIB_DANGER_GET( &pElementTypeDescr
, ((typelib_IndirectTypeDescription
*)pTypeDescr
)->pType
);
173 sal_Int32 nElementSize
= pElementTypeDescr
->nSize
;
174 sal_Int32 nElements
= pSequence
->nElements
;
179 char * pElements
= pSequence
->elements
;
180 for ( sal_Int32 nPos
= 0; nPos
< nElements
; ++nPos
)
182 buf
.append( val2str( pElements
+ (nElementSize
* nPos
), pElementTypeDescr
->pWeakRef
, mode
) );
183 if (nPos
< (nElements
-1))
192 TYPELIB_DANGER_RELEASE( pElementTypeDescr
);
193 TYPELIB_DANGER_RELEASE( pTypeDescr
);
196 case typelib_TypeClass_ANY
:
198 buf
.append( val2str( ((uno_Any
*)pVal
)->pData
,
199 ((uno_Any
*)pVal
)->pType
,
203 case typelib_TypeClass_TYPE
:
204 buf
.append( (*(typelib_TypeDescriptionReference
**)pVal
)->pTypeName
);
206 case typelib_TypeClass_STRING
:
207 buf
.append( (sal_Unicode
)'\"' );
208 buf
.append( *(rtl_uString
**)pVal
);
209 buf
.append( (sal_Unicode
)'\"' );
211 case typelib_TypeClass_ENUM
:
213 typelib_TypeDescription
* pTypeDescr
= 0;
214 TYPELIB_DANGER_GET( &pTypeDescr
, pTypeRef
);
216 sal_Int32
* pValues
= ((typelib_EnumTypeDescription
*)pTypeDescr
)->pEnumValues
;
217 sal_Int32 nPos
= ((typelib_EnumTypeDescription
*)pTypeDescr
)->nEnumValues
;
220 if (pValues
[nPos
] == *(int *)pVal
)
224 buf
.append( ((typelib_EnumTypeDescription
*)pTypeDescr
)->ppEnumNames
[nPos
] );
226 buf
.append( (sal_Unicode
)'?' );
228 TYPELIB_DANGER_RELEASE( pTypeDescr
);
231 case typelib_TypeClass_BOOLEAN
:
232 if (*(sal_Bool
*)pVal
)
233 buf
.append( "true" );
235 buf
.append( "false" );
237 case typelib_TypeClass_CHAR
:
238 buf
.append( (sal_Unicode
)'\'' );
239 buf
.append( *(sal_Unicode
*)pVal
);
240 buf
.append( (sal_Unicode
)'\'' );
242 case typelib_TypeClass_FLOAT
:
243 buf
.append( *(float *)pVal
);
245 case typelib_TypeClass_DOUBLE
:
246 buf
.append( *(double *)pVal
);
248 case typelib_TypeClass_BYTE
:
250 buf
.append( (sal_Int32
)*(sal_Int8
*)pVal
, 16 );
252 case typelib_TypeClass_SHORT
:
254 buf
.append( (sal_Int32
)*(sal_Int16
*)pVal
, 16 );
256 case typelib_TypeClass_UNSIGNED_SHORT
:
258 buf
.append( (sal_Int32
)*(sal_uInt16
*)pVal
, 16 );
260 case typelib_TypeClass_LONG
:
262 buf
.append( *(sal_Int32
*)pVal
, 16 );
264 case typelib_TypeClass_UNSIGNED_LONG
:
266 buf
.append( (sal_Int64
)*(sal_uInt32
*)pVal
, 16 );
268 case typelib_TypeClass_HYPER
:
269 case typelib_TypeClass_UNSIGNED_HYPER
:
271 #if defined(__GNUC__) && defined(SPARC)
272 // I guess this really should check if there are strict alignment
273 // requirements, not just "GCC on SPARC".
276 *(sal_Int32
*)&aVal
= *(sal_Int32
*)pVal
;
277 *((sal_Int32
*)&aVal
+1)= *((sal_Int32
*)pVal
+1);
278 buf
.append( aVal
, 16 );
281 buf
.append( *(sal_Int64
*)pVal
, 16 );
285 case typelib_TypeClass_VOID
:
286 case typelib_TypeClass_ARRAY
:
287 case typelib_TypeClass_UNKNOWN
:
288 case typelib_TypeClass_SERVICE
:
289 case typelib_TypeClass_MODULE
:
291 buf
.append( (sal_Unicode
)'?' );
294 return buf
.makeStringAndClear();
298 PyObject
*PyUNO_repr( PyObject
* self
)
300 PyUNO
*me
= (PyUNO
* ) self
;
303 if( me
->members
->wrappedObject
.getValueType().getTypeClass()
304 == com::sun::star::uno::TypeClass_EXCEPTION
)
306 Reference
< XMaterialHolder
> rHolder(me
->members
->xInvocation
,UNO_QUERY
);
309 Any a
= rHolder
->getMaterial();
312 ret
= ustring2PyUnicode(e
.Message
).getAcquired();
317 ret
= PyUNO_str( self
);
322 PyObject
*PyUNO_invoke( PyObject
*object
, const char *name
, PyObject
*args
)
329 PyRef paras
,callable
;
330 if( PyObject_IsInstance( object
, getPyUnoClass().get() ) )
332 PyUNO
* me
= (PyUNO
*) object
;
333 OUString attrName
= OUString::createFromAscii(name
);
334 if (! me
->members
->xInvocation
->hasMethod (attrName
))
337 buf
.append( "Attribute " );
338 buf
.append( attrName
);
339 buf
.append( " unknown" );
340 throw RuntimeException( buf
.makeStringAndClear(), Reference
< XInterface
> () );
342 callable
= PyUNO_callable_new (
343 me
->members
->xInvocation
,
350 // clean the tuple from uno.Any !
351 int size
= PyTuple_Size( args
);
352 { // for CC, keeping ref-count of tuple being 1
353 paras
= PyRef(PyTuple_New( size
), SAL_NO_ACQUIRE
);
355 for( int i
= 0 ; i
< size
;i
++ )
357 PyObject
* element
= PyTuple_GetItem( args
, i
);
358 if( PyObject_IsInstance( element
, getAnyClass( runtime
).get() ) )
360 element
= PyObject_GetAttrString(
365 Py_XINCREF( element
);
367 PyTuple_SetItem( paras
.get(), i
, element
);
369 callable
= PyRef( PyObject_GetAttrString( object
, (char*)name
), SAL_NO_ACQUIRE
);
373 ret
= PyRef( PyObject_CallObject( callable
.get(), paras
.get() ), SAL_NO_ACQUIRE
);
375 catch (const ::com::sun::star::lang::IllegalArgumentException
&e
)
377 raisePyExceptionWithAny( com::sun::star::uno::makeAny( e
) );
379 catch (const ::com::sun::star::script::CannotConvertException
&e
)
381 raisePyExceptionWithAny( com::sun::star::uno::makeAny( e
) );
383 catch (const ::com::sun::star::uno::RuntimeException
&e
)
385 raisePyExceptionWithAny( com::sun::star::uno::makeAny( e
) );
387 catch (const ::com::sun::star::uno::Exception
&e
)
389 raisePyExceptionWithAny( com::sun::star::uno::makeAny( e
) );
392 return ret
.getAcquired();
395 PyObject
*PyUNO_str( PyObject
* self
)
397 PyUNO
*me
= ( PyUNO
* ) self
;
402 if( me
->members
->wrappedObject
.getValueType().getTypeClass()
403 == com::sun::star::uno::TypeClass_STRUCT
||
404 me
->members
->wrappedObject
.getValueType().getTypeClass()
405 == com::sun::star::uno::TypeClass_EXCEPTION
)
407 Reference
< XMaterialHolder
> rHolder(me
->members
->xInvocation
,UNO_QUERY
);
410 PyThreadDetach antiguard
;
411 Any a
= rHolder
->getMaterial();
412 OUString s
= val2str( (void*) a
.getValue(), a
.getValueType().getTypeLibType() );
413 buf
.append( OUStringToOString(s
,RTL_TEXTENCODING_ASCII_US
) );
418 // a common UNO object
419 PyThreadDetach antiguard
;
420 buf
.append( "pyuno object " );
422 OUString s
= val2str( (void*)me
->members
->wrappedObject
.getValue(),
423 me
->members
->wrappedObject
.getValueType().getTypeLibType() );
424 buf
.append( OUStringToOString(s
,RTL_TEXTENCODING_ASCII_US
) );
427 return PyStr_FromString( buf
.getStr());
430 PyObject
* PyUNO_dir (PyObject
* self
)
432 PyUNO
* me
= (PyUNO
*) self
;
434 PyObject
* member_list
= NULL
;
435 Sequence
<OUString
> oo_member_list
;
439 oo_member_list
= me
->members
->xInvocation
->getMemberNames ();
440 member_list
= PyList_New (oo_member_list
.getLength ());
441 for (int i
= 0; i
< oo_member_list
.getLength (); i
++)
443 // setitem steals a reference
444 PyList_SetItem (member_list
, i
, ustring2PyString(oo_member_list
[i
]).getAcquired() );
447 catch( const RuntimeException
&e
)
449 raisePyExceptionWithAny( makeAny(e
) );
456 PyObject
* PyUNO_getattr (PyObject
* self
, char* name
)
466 if (strcmp (name
, "__dict__") == 0)
468 Py_INCREF (Py_TYPE(me
)->tp_dict
);
469 return Py_TYPE(me
)->tp_dict
;
471 if (strcmp (name
, "__class__") == 0)
473 if( me
->members
->wrappedObject
.getValueTypeClass() ==
474 com::sun::star::uno::TypeClass_STRUCT
||
475 me
->members
->wrappedObject
.getValueTypeClass() ==
476 com::sun::star::uno::TypeClass_EXCEPTION
)
479 me
->members
->wrappedObject
.getValueType().getTypeName(), runtime
).getAcquired();
485 OUString
attrName( OUString::createFromAscii( name
) );
486 //We need to find out if it's a method...
487 if (me
->members
->xInvocation
->hasMethod (attrName
))
489 //Create a callable object to invoke this...
490 PyRef ret
= PyUNO_callable_new (
491 me
->members
->xInvocation
,
493 Py_XINCREF( ret
.get() );
499 if (me
->members
->xInvocation
->hasProperty ( attrName
))
501 //Return the value of the property
504 PyThreadDetach antiguard
;
505 anyRet
= me
->members
->xInvocation
->getValue (attrName
);
507 PyRef ret
= runtime
.any2PyObject(anyRet
);
508 Py_XINCREF( ret
.get() );
513 PyErr_SetString (PyExc_AttributeError
, name
);
515 catch( const com::sun::star::reflection::InvocationTargetException
& e
)
517 raisePyExceptionWithAny( makeAny(e
.TargetException
) );
519 catch( const com::sun::star::beans::UnknownPropertyException
& e
)
521 raisePyExceptionWithAny( makeAny(e
) );
523 catch( const com::sun::star::lang::IllegalArgumentException
&e
)
525 raisePyExceptionWithAny( makeAny(e
) );
527 catch( const com::sun::star::script::CannotConvertException
&e
)
529 raisePyExceptionWithAny( makeAny(e
) );
531 catch( const RuntimeException
&e
)
533 raisePyExceptionWithAny( makeAny(e
) );
539 int PyUNO_setattr (PyObject
* self
, char* name
, PyObject
* value
)
547 Any val
= runtime
.pyObject2Any(value
, ACCEPT_UNO_ANY
);
549 OUString
attrName( OUString::createFromAscii( name
) );
551 PyThreadDetach antiguard
;
552 if (me
->members
->xInvocation
->hasProperty (attrName
))
554 me
->members
->xInvocation
->setValue (attrName
, val
);
555 return 0; //Keep with Python's boolean system
559 catch( const com::sun::star::reflection::InvocationTargetException
& e
)
561 raisePyExceptionWithAny( makeAny(e
.TargetException
) );
564 catch( const com::sun::star::beans::UnknownPropertyException
& e
)
566 raisePyExceptionWithAny( makeAny(e
) );
569 catch( const com::sun::star::script::CannotConvertException
&e
)
571 raisePyExceptionWithAny( makeAny(e
) );
574 catch( const RuntimeException
& e
)
576 raisePyExceptionWithAny( makeAny( e
) );
579 PyErr_SetString (PyExc_AttributeError
, name
);
580 return 1; //as above.
583 // ensure object identity and struct equality
584 static PyObject
* PyUNO_cmp( PyObject
*self
, PyObject
*that
, int op
)
588 if(op
!= Py_EQ
&& op
!= Py_NE
)
590 PyErr_SetString(PyExc_TypeError
, "only '==' and '!=' comparisions are defined");
595 result
= (op
== Py_EQ
? Py_True
: Py_False
);
602 if( PyObject_IsInstance( that
, getPyUnoClass().get() ) )
605 PyUNO
*me
= reinterpret_cast< PyUNO
*> ( self
);
606 PyUNO
*other
= reinterpret_cast< PyUNO
*> (that
);
607 com::sun::star::uno::TypeClass tcMe
= me
->members
->wrappedObject
.getValueTypeClass();
608 com::sun::star::uno::TypeClass tcOther
= other
->members
->wrappedObject
.getValueTypeClass();
610 if( tcMe
== tcOther
)
612 if( tcMe
== com::sun::star::uno::TypeClass_STRUCT
||
613 tcMe
== com::sun::star::uno::TypeClass_EXCEPTION
)
615 Reference
< XMaterialHolder
> xMe( me
->members
->xInvocation
,UNO_QUERY
);
616 Reference
< XMaterialHolder
> xOther( other
->members
->xInvocation
,UNO_QUERY
);
617 if( xMe
->getMaterial() == xOther
->getMaterial() )
619 result
= (op
== Py_EQ
? Py_True
: Py_False
);
624 else if( tcMe
== com::sun::star::uno::TypeClass_INTERFACE
)
626 if( me
->members
->wrappedObject
== other
->members
->wrappedObject
)
628 result
= (op
== Py_EQ
? Py_True
: Py_False
);
636 catch( const com::sun::star::uno::RuntimeException
& e
)
638 raisePyExceptionWithAny( makeAny( e
) );
641 result
= (op
== Py_EQ
? Py_False
: Py_True
);
646 static PyMethodDef PyUNOMethods
[] =
648 {"__dir__", (PyCFunction
)PyUNO_dir
, METH_NOARGS
, NULL
},
649 {NULL
, NULL
, 0, NULL
}
653 /* Python 2 has a tp_flags value for rich comparisons. Python 3 does not (on by default) */
654 #ifdef Py_TPFLAGS_HAVE_RICHCOMPARE
655 #define TP_FLAGS (Py_TPFLAGS_HAVE_RICHCOMPARE)
660 static PyTypeObject PyUNOType
=
662 PyVarObject_HEAD_INIT( &PyType_Type
, 0 )
666 (destructor
) PyUNO_del
,
668 (getattrfunc
) PyUNO_getattr
,
669 (setattrfunc
) PyUNO_setattr
,
670 /* this type does not exist in Python 3: (cmpfunc) */ 0,
671 (reprfunc
) PyUNO_repr
,
677 (reprfunc
) PyUNO_str
,
685 (richcmpfunc
) PyUNO_cmp
,
708 #if PY_VERSION_HEX >= 0x02060000
715 return PyType_Ready(&PyUNOType
);
718 PyRef
getPyUnoClass()
720 return PyRef( reinterpret_cast< PyObject
* > ( &PyUNOType
) );
723 PyObject
* PyUNO_new (
724 const Any
& targetInterface
, const Reference
<XSingleServiceFactory
> &ssf
)
726 Reference
<XInterface
> tmp_interface
;
728 targetInterface
>>= tmp_interface
;
730 if (!tmp_interface
.is ())
733 Py_INCREF( Py_None
);
736 return PyUNO_new_UNCHECKED (targetInterface
, ssf
);
740 PyObject
* PyUNO_new_UNCHECKED (
741 const Any
&targetInterface
,
742 const Reference
<XSingleServiceFactory
> &ssf
)
745 Sequence
<Any
> arguments (1);
746 Reference
<XInterface
> tmp_interface
;
748 self
= PyObject_New (PyUNO
, &PyUNOType
);
750 return NULL
; // == error
751 self
->members
= new PyUNOInternals();
753 arguments
[0] <<= targetInterface
;
755 PyThreadDetach antiguard
;
756 tmp_interface
= ssf
->createInstanceWithArguments (arguments
);
758 if (!tmp_interface
.is ())
760 Py_INCREF( Py_None
);
764 Reference
<XInvocation2
> tmp_invocation (tmp_interface
, UNO_QUERY
);
765 if (!tmp_invocation
.is()) {
766 throw RuntimeException (OUString::createFromAscii (
767 "XInvocation2 not implemented, cannot interact with object"),
768 Reference
< XInterface
> ());
771 self
->members
->xInvocation
= tmp_invocation
;
772 self
->members
->wrappedObject
= targetInterface
;
774 return (PyObject
*) self
;
779 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */