LibreOffice Module pyuno (master) 1
pyuno_struct.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <sal/config.h>
21
22#include <com/sun/star/beans/UnknownPropertyException.hpp>
23#include <com/sun/star/beans/XMaterialHolder.hpp>
24#include <com/sun/star/script/CannotConvertException.hpp>
25#include <com/sun/star/script/XInvocation2.hpp>
26#include <com/sun/star/lang/XSingleServiceFactory.hpp>
27
28#include "pyuno_impl.hxx"
29
32using com::sun::star::uno::Any;
33using com::sun::star::uno::UNO_QUERY;
34using com::sun::star::uno::TypeClass;
35using com::sun::star::uno::RuntimeException;
36using com::sun::star::uno::Exception;
37using com::sun::star::lang::XSingleServiceFactory;
38using com::sun::star::script::XInvocation2;
39using com::sun::star::beans::XMaterialHolder;
40
41namespace pyuno
42{
43
44static void PyUNOStruct_del( PyObject* self )
45{
46 PyUNO *me = reinterpret_cast<PyUNO*>( self );
47 {
48 PyThreadDetach antiguard;
49 delete me->members;
50 }
51 PyObject_Del( self );
52}
53
54static PyObject *PyUNOStruct_str( PyObject *self )
55{
56 PyUNO *me = reinterpret_cast<PyUNO*>( self );
57 OString buf;
58
59 Reference<XMaterialHolder> rHolder( me->members->xInvocation,UNO_QUERY );
60 if( rHolder.is() )
61 {
62 PyThreadDetach antiguard;
63 Any a = rHolder->getMaterial();
64 OUString s = val2str( a.getValue(), a.getValueType().getTypeLibType() );
65 buf = OUStringToOString( s, RTL_TEXTENCODING_ASCII_US );
66 }
67
68 return PyUnicode_FromString( buf.getStr());
69}
70
71static PyObject *PyUNOStruct_repr( PyObject *self )
72{
73 PyUNO *me = reinterpret_cast<PyUNO*>( self );
74 PyObject *ret = nullptr;
75
76 if( me->members->wrappedObject.getValueType().getTypeClass()
77 == css::uno::TypeClass_EXCEPTION )
78 {
79 Reference< XMaterialHolder > rHolder(me->members->xInvocation,UNO_QUERY);
80 if( rHolder.is() )
81 {
82 Any a = rHolder->getMaterial();
83 Exception e;
84 a >>= e;
85 ret = ustring2PyUnicode(e.Message ).getAcquired();
86 }
87 }
88 else
89 {
90 ret = PyUNOStruct_str( self );
91 }
92
93 return ret;
94}
95
96static PyObject* PyUNOStruct_dir( PyObject *self )
97{
98 PyUNO *me = reinterpret_cast<PyUNO*>( self );
99
100 PyObject* member_list = nullptr;
101
102 try
103 {
104 member_list = PyList_New( 0 );
105 const css::uno::Sequence<OUString> aMemberNames = me->members->xInvocation->getMemberNames();
106 for( const auto& aMember : aMemberNames )
107 {
108 // setitem steals a reference
109 PyList_Append( member_list, ustring2PyString( aMember ).getAcquired() );
110 }
111 }
112 catch( const RuntimeException &e )
113 {
115 }
116
117 return member_list;
118}
119
120static PyObject* PyUNOStruct_getattr( PyObject* self, char* name )
121{
122 PyUNO *me = reinterpret_cast<PyUNO*>( self );
123
124 try
125 {
126 Runtime runtime;
127
128 me = reinterpret_cast<PyUNO*>(self);
129 if (strcmp (name, "__dict__") == 0)
130 {
131 Py_INCREF (Py_TYPE(me)->tp_dict);
132 return Py_TYPE(me)->tp_dict;
133 }
134 if( strcmp( name, "__class__" ) == 0 )
135 {
136 return getClass(
137 me->members->wrappedObject.getValueType().getTypeName(), runtime ).getAcquired();
138 }
139
140 PyObject *pRet = PyObject_GenericGetAttr( self, PyUnicode_FromString( name ) );
141 if( pRet )
142 return pRet;
143 PyErr_Clear();
144
145 OUString attrName( OUString::createFromAscii( name ) );
146 if( me->members->xInvocation->hasProperty( attrName ) )
147 {
148 //Return the value of the property
149 Any anyRet;
150 {
151 PyThreadDetach antiguard;
152 anyRet = me->members->xInvocation->getValue( attrName );
153 }
154 PyRef ret = runtime.any2PyObject( anyRet );
155 Py_XINCREF( ret.get() );
156 return ret.get();
157 }
158
159 //or else...
160 PyErr_SetString (PyExc_AttributeError, name);
161 }
162 catch( const css::reflection::InvocationTargetException & e )
163 {
164 raisePyExceptionWithAny( e.TargetException );
165 }
166 catch( const css::beans::UnknownPropertyException & e )
167 {
169 }
170 catch( const css::lang::IllegalArgumentException &e )
171 {
173 }
174 catch( const css::script::CannotConvertException &e )
175 {
177 }
178 catch( const RuntimeException &e )
179 {
181 }
182
183 return nullptr;
184}
185
186static int PyUNOStruct_setattr (PyObject* self, char* name, PyObject* value)
187{
188 PyUNO* me;
189
190 me = reinterpret_cast<PyUNO*>(self);
191 try
192 {
193 Runtime runtime;
194 Any val= runtime.pyObject2Any(value, ACCEPT_UNO_ANY);
195
196 OUString attrName( OUString::createFromAscii( name ) );
197 {
198 PyThreadDetach antiguard;
199 if (me->members->xInvocation->hasProperty (attrName))
200 {
201 me->members->xInvocation->setValue (attrName, val);
202 return 0; //Keep with Python's boolean system
203 }
204 }
205 }
206 catch( const css::reflection::InvocationTargetException & e )
207 {
208 raisePyExceptionWithAny( e.TargetException );
209 return 1;
210 }
211 catch( const css::beans::UnknownPropertyException & e )
212 {
214 return 1;
215 }
216 catch( const css::script::CannotConvertException &e )
217 {
219 return 1;
220 }
221 catch( const RuntimeException & e )
222 {
224 return 1;
225 }
226 PyErr_SetString (PyExc_AttributeError, name);
227 return 1; //as above.
228}
229
230
231static PyObject* PyUNOStruct_cmp( PyObject *self, PyObject *that, int op )
232{
233 PyObject *result;
234
235 if(op != Py_EQ && op != Py_NE)
236 {
237 PyErr_SetString( PyExc_TypeError, "only '==' and '!=' comparisons are defined" );
238 return nullptr;
239 }
240 if( self == that )
241 {
242 result = (op == Py_EQ ? Py_True : Py_False);
243 Py_INCREF( result );
244 return result;
245 }
246 try
247 {
248 Runtime runtime;
249 if( PyObject_IsInstance( that, getPyUnoStructClass().get() ) )
250 {
251
252 PyUNO *me = reinterpret_cast< PyUNO * > ( self );
253 PyUNO *other = reinterpret_cast< PyUNO * > ( that );
254 css::uno::TypeClass tcMe = me->members->wrappedObject.getValueTypeClass();
255 css::uno::TypeClass tcOther = other->members->wrappedObject.getValueTypeClass();
256
257 if( tcMe == tcOther )
258 {
259 if( tcMe == css::uno::TypeClass_STRUCT ||
260 tcMe == css::uno::TypeClass_EXCEPTION )
261 {
263 Reference< XMaterialHolder > xOther( other->members->xInvocation,UNO_QUERY );
264 if( xMe->getMaterial() == xOther->getMaterial() )
265 {
266 result = (op == Py_EQ ? Py_True : Py_False);
267 Py_INCREF( result );
268 return result;
269 }
270 }
271 }
272 }
273 }
274 catch( const css::uno::RuntimeException & e)
275 {
277 }
278
279 result = (op == Py_EQ ? Py_False : Py_True);
280 Py_INCREF(result);
281 return result;
282}
283
284static PyMethodDef PyUNOStructMethods[] =
285{
286 {"__dir__", reinterpret_cast<PyCFunction>(PyUNOStruct_dir), METH_NOARGS, nullptr},
287 {nullptr, nullptr, 0, nullptr}
288};
289
290static PyTypeObject PyUNOStructType =
291{
292 PyVarObject_HEAD_INIT( &PyType_Type, 0 )
293 "pyuno.struct",
294 sizeof (PyUNO),
295 0,
297#if PY_VERSION_HEX >= 0x03080000
298 0, // Py_ssize_t tp_vectorcall_offset
299#else
300 nullptr, // printfunc tp_print
301#endif
304 /* this type does not exist in Python 3: (cmpfunc) */ nullptr,
306 nullptr,
307 nullptr,
308 nullptr,
309 nullptr,
310 nullptr,
312 nullptr,
313 nullptr,
314 nullptr,
316 nullptr,
317 nullptr,
318 nullptr,
320 0,
321 nullptr,
322 nullptr,
324 nullptr,
325 nullptr,
326 nullptr,
327 nullptr,
328 nullptr,
329 nullptr,
330 0,
331 nullptr,
332 nullptr,
333 nullptr,
334 nullptr,
335 nullptr,
336 nullptr,
337 nullptr,
338 nullptr,
339 nullptr,
340 nullptr,
341 nullptr
342 , 0
343#if PY_VERSION_HEX >= 0x03040000
344 , nullptr
345#if PY_VERSION_HEX >= 0x03080000
346 , nullptr // vectorcallfunc tp_vectorcall
347#if PY_VERSION_HEX < 0x03090000
348#if defined __clang__
349#pragma clang diagnostic push
350#pragma clang diagnostic ignored "-Wdeprecated-declarations"
351#endif
352 , nullptr // tp_print
353#if defined __clang__
354#pragma clang diagnostic pop
355#endif
356#endif
357#endif
358#endif
359};
360
362{
363 return PyType_Ready( &PyUNOStructType );
364}
365
367{
368 return PyRef( reinterpret_cast< PyObject * > ( &PyUNOStructType ) );
369}
370
372 const Any &targetInterface,
374{
376
377 {
378 PyThreadDetach antiguard;
379 xInvocation.set(
380 ssf->createInstanceWithArguments( Sequence<Any>( &targetInterface, 1 ) ), css::uno::UNO_QUERY_THROW );
381 }
382 if( !Py_IsInitialized() )
383 throw RuntimeException();
384
385 PyUNO* self = PyObject_New (PyUNO, &PyUNOStructType);
386 if (self == nullptr)
387 return PyRef(); // == error
388 self->members = new PyUNOInternals;
390 self->members->wrappedObject = targetInterface;
391 return PyRef( reinterpret_cast<PyObject*>(self), SAL_NO_ACQUIRE );
392
393}
394
395}
396
397/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Helper class for keeping references to python objects.
Definition: pyuno.hxx:80
PyObject * get() const noexcept
Definition: pyuno.hxx:99
PyObject * getAcquired() const
Definition: pyuno.hxx:101
helper class for detaching the current thread from the python runtime to do some blocking,...
Definition: pyuno.hxx:300
The pyuno::Runtime class keeps the internal state of the python UNO bridge for the currently in use p...
Definition: pyuno.hxx:164
css::uno::Any pyObject2Any(const PyRef &source, enum ConversionMode mode=REJECT_UNO_ANY) const
converts a Python object to a UNO any
PyRef any2PyObject(const css::uno::Any &source) const
converts something contained in a UNO Any to a Python object
Any value
const char * name
uno_Any a
const char * attrName
@ Exception
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
Definition: pyuno.cxx:72
static PyTypeObject PyUNOStructType
static PyObject * PyUNOStruct_getattr(PyObject *self, char *name)
static void PyUNOStruct_del(PyObject *self)
static int PyUNOStruct_setattr(PyObject *self, char *name, PyObject *value)
@ ACCEPT_UNO_ANY
Definition: pyuno.hxx:153
static PyObject * PyUNOStruct_cmp(PyObject *self, PyObject *that, int op)
PyRef getPyUnoStructClass()
static PyObject * PyUNOStruct_dir(PyObject *self)
int PyUNOStruct_initType()
PyRef ustring2PyString(std::u16string_view source)
Definition: pyuno_util.cxx:51
static PyMethodDef PyUNOStructMethods[]
void raisePyExceptionWithAny(const css::uno::Any &anyExc)
static PyObject * PyUNOStruct_str(PyObject *self)
OUString val2str(const void *pVal, typelib_TypeDescriptionReference *pTypeRef, sal_Int32 mode)
Definition: pyuno.cxx:87
PyRef ustring2PyUnicode(const OUString &source)
Definition: pyuno_util.cxx:34
PyRef getClass(const OUString &name, const Runtime &runtime)
static PyObject * PyUNOStruct_repr(PyObject *self)
PyRef PyUNOStruct_new(const css::uno::Any &targetInterface, const css::uno::Reference< css::lang::XSingleServiceFactory > &ssf)
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
Reference< XInvocation2 > xInvocation
#define Py_TPFLAGS_HAVE_RICHCOMPARE
Definition: pyuno_impl.hxx:33
css::uno::Any wrappedObject
Definition: pyuno_impl.hxx:132
css::uno::Reference< css::script::XInvocation2 > xInvocation
Definition: pyuno_impl.hxx:131
PyObject_HEAD PyUNOInternals * members
Definition: pyuno_impl.hxx:138
Any result