LibreOffice Module pyuno (master) 1
pyuno_callable.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#include "pyuno_impl.hxx"
20
21#include <osl/diagnose.h>
22
23#include <com/sun/star/script/CannotConvertException.hpp>
24#include <com/sun/star/script/XInvocation2.hpp>
25
28using com::sun::star::uno::Any;
29using com::sun::star::uno::RuntimeException;
30using com::sun::star::script::XInvocation2;
31
32namespace pyuno
33{
34namespace {
35
36struct PyUNO_callable_Internals
37{
39 OUString methodName;
41};
42
43struct PyUNO_callable
44{
45 PyObject_HEAD
46 PyUNO_callable_Internals* members;
47};
48
49}
50
51static void PyUNO_callable_del (PyObject* self)
52{
53 PyUNO_callable* me;
54
55 me = reinterpret_cast<PyUNO_callable*>(self);
56 delete me->members;
57 PyObject_Del (self);
58}
59
60static PyObject* PyUNO_callable_call(
61 PyObject* self, PyObject* args, SAL_UNUSED_PARAMETER PyObject*)
62{
63 PyUNO_callable* me;
64
65 Sequence<short> aOutParamIndex;
66 Sequence<Any> aOutParam;
67 Sequence<Any> aParams;
68 Any any_params;
69 Any ret_value;
70 RuntimeCargo *cargo = nullptr;
71 me = reinterpret_cast<PyUNO_callable*>(self);
72
73 PyRef ret;
74 try
75 {
76 Runtime runtime;
77 cargo = runtime.getImpl()->cargo;
78 any_params = runtime.pyObject2Any (args, me->members->mode);
79
80 if (any_params.getValueTypeClass () == css::uno::TypeClass_SEQUENCE)
81 {
82 any_params >>= aParams;
83 }
84 else
85 {
86 aParams = { any_params };
87 }
88
89 {
90 PyThreadDetach antiguard; //python free zone
91
92 // do some logging if desired ...
93 if( isLog( cargo, LogLevel::CALL ) )
94 {
95 logCall( cargo, "try py->uno[0x", me->members->xInvocation.get(),
96 me->members->methodName, aParams );
97 }
98
99 // do the call
100 ret_value = me->members->xInvocation->invoke (
101 me->members->methodName, aParams, aOutParamIndex, aOutParam);
102
103 // log the reply, if desired
104 if( isLog( cargo, LogLevel::CALL ) )
105 {
106 logReply( cargo, "success py->uno[0x", me->members->xInvocation.get(),
107 me->members->methodName, ret_value, aOutParam);
108 }
109 }
110
111
112 PyRef temp = runtime.any2PyObject (ret_value);
113 if( aOutParam.getLength() )
114 {
115 PyRef return_list( PyTuple_New (1+aOutParam.getLength()), SAL_NO_ACQUIRE, NOT_NULL );
116 PyTuple_SetItem (return_list.get(), 0, temp.getAcquired());
117
118 // initialize with defaults in case of exceptions
119 int i;
120 for( i = 1 ; i < 1+aOutParam.getLength() ; i ++ )
121 {
122 Py_INCREF( Py_None );
123 PyTuple_SetItem( return_list.get() , i , Py_None );
124 }
125
126 for( i = 0 ; i < aOutParam.getLength() ; i ++ )
127 {
128 PyRef ref = runtime.any2PyObject( aOutParam[i] );
129 PyTuple_SetItem (return_list.get(), 1+i, ref.getAcquired());
130 }
131 ret = return_list;
132 }
133 else
134 {
135 ret = temp;
136 }
137 }
138 catch( const css::reflection::InvocationTargetException & e )
139 {
140
141 if( isLog( cargo, LogLevel::CALL ) )
142 {
143 logException( cargo, "except py->uno[0x", me->members->xInvocation.get() ,
144 me->members->methodName, e.TargetException.getValue(), e.TargetException.getValueTypeRef());
145 }
146 raisePyExceptionWithAny( e.TargetException );
147 }
148 catch( const css::script::CannotConvertException &e )
149 {
150 if( isLog( cargo, LogLevel::CALL ) )
151 {
152 logException( cargo, "error py->uno[0x", me->members->xInvocation.get() ,
153 me->members->methodName, &e, cppu::UnoType<decltype(e)>::get().getTypeLibType());
154 }
155 raisePyExceptionWithAny( css::uno::Any( e ) );
156 }
157 catch( const css::lang::IllegalArgumentException &e )
158 {
159 if( isLog( cargo, LogLevel::CALL ) )
160 {
161 logException( cargo, "error py->uno[0x", me->members->xInvocation.get() ,
162 me->members->methodName, &e, cppu::UnoType<decltype(e)>::get().getTypeLibType());
163 }
164 raisePyExceptionWithAny( css::uno::Any( e ) );
165 }
166 catch (const css::uno::RuntimeException &e)
167 {
168 if( cargo && isLog( cargo, LogLevel::CALL ) )
169 {
170 logException( cargo, "error py->uno[0x", me->members->xInvocation.get() ,
171 me->members->methodName, &e, cppu::UnoType<decltype(e)>::get().getTypeLibType());
172 }
173 raisePyExceptionWithAny( css::uno::Any( e ) );
174 }
175
176 return ret.getAcquired();
177}
178
179
180static PyTypeObject PyUNO_callable_Type =
181{
182 PyVarObject_HEAD_INIT( &PyType_Type, 0 )
183 "PyUNO_callable",
184 sizeof (PyUNO_callable),
185 0,
187#if PY_VERSION_HEX >= 0x03080000
188 0, // Py_ssize_t tp_vectorcall_offset
189#else
190 nullptr, // printfunc tp_print
191#endif
192 nullptr,
193 nullptr,
194 nullptr,
195 nullptr,
196 nullptr,
197 nullptr,
198 nullptr,
199 nullptr,
201 nullptr,
202 nullptr,
203 nullptr,
204 nullptr,
205 0,
206 nullptr,
207 nullptr,
208 nullptr,
209 nullptr,
210 0,
211 nullptr,
212 nullptr,
213 nullptr,
214 nullptr,
215 nullptr,
216 nullptr,
217 nullptr,
218 nullptr,
219 nullptr,
220 0,
221 nullptr,
222 nullptr,
223 nullptr,
224 nullptr,
225 nullptr,
226 nullptr,
227 nullptr,
228 nullptr,
229 nullptr,
230 nullptr,
231 nullptr
232 , 0
233#if PY_VERSION_HEX >= 0x03040000
234 , nullptr
235#if PY_VERSION_HEX >= 0x03080000
236 , nullptr // vectorcallfunc tp_vectorcall
237#if PY_VERSION_HEX < 0x03090000
238#if defined __clang__
239#pragma clang diagnostic push
240#pragma clang diagnostic ignored "-Wdeprecated-declarations"
241#endif
242 , nullptr // tp_print
243#if defined __clang__
244#pragma clang diagnostic pop
245#endif
246#endif
247#endif
248#endif
249};
250
252 const Reference<XInvocation2> &my_inv,
253 const OUString & methodName,
254 enum ConversionMode mode )
255{
256 PyUNO_callable* self;
257
258 OSL_ENSURE (my_inv.is(), "XInvocation must be valid");
259
260 self = PyObject_New (PyUNO_callable, &PyUNO_callable_Type);
261 if (self == nullptr)
262 return nullptr; //NULL == Error!
263
264 self->members = new PyUNO_callable_Internals;
265 self->members->xInvocation = my_inv;
266 self->members->methodName = methodName;
267 self->members->mode = mode;
268
269 return PyRef( reinterpret_cast<PyObject*>(self), SAL_NO_ACQUIRE );
270}
271
272}
273
274/* 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
RuntimeImpl * getImpl() const
Returns the internal handle.
Definition: pyuno.hxx:242
int i
args
const sal_Int32 CALL
Definition: pyuno_impl.hxx:74
Definition: pyuno.cxx:72
bool isLog(RuntimeCargo const *cargo, sal_Int32 loglevel)
Definition: pyuno_util.cxx:93
void logCall(RuntimeCargo *cargo, const char *intro, void *ptr, std::u16string_view aFunctionName, const css::uno::Sequence< css::uno::Any > &args)
ConversionMode
Definition: pyuno.hxx:153
static PyObject * PyUNO_callable_call(PyObject *self, PyObject *args, SAL_UNUSED_PARAMETER PyObject *)
static PyTypeObject PyUNO_callable_Type
void raisePyExceptionWithAny(const css::uno::Any &anyExc)
void logException(RuntimeCargo *cargo, const char *intro, void *ptr, std::u16string_view aFunctionName, const void *data, const css::uno::Type &type)
Definition: pyuno_util.cxx:145
@ NOT_NULL
definition of a no acquire enum for ctors
Definition: pyuno.hxx:65
static void PyUNO_callable_del(PyObject *self)
PyRef PyUNO_callable_new(const Reference< XInvocation2 > &my_inv, const OUString &methodName, enum ConversionMode mode)
void logReply(RuntimeCargo *cargo, const char *intro, void *ptr, std::u16string_view aFunctionName, const css::uno::Any &returnValue, const css::uno::Sequence< css::uno::Any > &args)
ConversionMode mode
PyObject_HEAD PyUNO_callable_Internals * members
OUString methodName
Reference< XInvocation2 > xInvocation
css::uno::Reference< css::lang::XSingleServiceFactory > xInvocation
Definition: pyuno_impl.hxx:216
PyObject_HEAD struct RuntimeCargo * cargo
Definition: pyuno_impl.hxx:238