Line data Source code
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 : #ifndef INCLUDED_PYUNO_INC_PYUNO_PYUNO_HXX
21 : #define INCLUDED_PYUNO_INC_PYUNO_PYUNO_HXX
22 :
23 : #ifndef Py_PYTHON_H
24 : #if defined _MSC_VER
25 : #pragma warning(push, 1)
26 : #endif
27 : #include <Python.h>
28 : #if defined _MSC_VER
29 : #pragma warning(pop)
30 : #endif
31 : #endif // #ifdef Py_PYTHON_H
32 : #include <com/sun/star/uno/XComponentContext.hpp>
33 : #include <com/sun/star/script/CannotConvertException.hpp>
34 : #include <com/sun/star/lang/IllegalArgumentException.hpp>
35 :
36 : /**
37 : External interface of the Python UNO bridge.
38 :
39 : This is a C++ interface, because the core UNO components
40 : invocation and proxyfactory are used to implement the bridge.
41 :
42 : This interface is somewhat private and my change in future.
43 :
44 : A scripting framework implementation may use this interface
45 : to do the necessary conversions.
46 : */
47 :
48 : #if defined LO_DLLIMPLEMENTATION_PYUNO
49 : #define LO_DLLPUBLIC_PYUNO SAL_DLLPUBLIC_EXPORT
50 : #else
51 : #define LO_DLLPUBLIC_PYUNO SAL_DLLPUBLIC_IMPORT
52 : #endif
53 :
54 : /** function called by the python runtime to initialize the
55 : pyuno module.
56 :
57 : preconditions: python has been initialized before and
58 : the global interpreter lock is held
59 : */
60 :
61 : extern "C" LO_DLLPUBLIC_PYUNO
62 : #if PY_MAJOR_VERSION >= 3
63 : PyObject* SAL_CALL PyInit_pyuno();
64 : #else
65 : void SAL_CALL initpyuno();
66 : #endif
67 :
68 : namespace pyuno
69 : {
70 :
71 : enum __NotNull
72 : {
73 : /** definition of a no acquire enum for ctors
74 : */
75 : NOT_NULL
76 : };
77 :
78 : /** Helper class for keeping references to python objects.
79 : BEWARE: Look up every python function you use to check
80 : whether you get an acquired or not acquired object pointer
81 : (python terminus for a not acquired object pointer
82 : is 'borrowed reference'). Use in the acquired pointer cases the
83 : PyRef( pointer, SAL_NO_ACQUIRE) ctor.
84 :
85 : precondition: python has been initialized before and
86 : the global interpreter lock is held
87 :
88 : */
89 : class PyRef
90 : {
91 : PyObject *m;
92 : public:
93 15460 : PyRef () : m(0) {}
94 14344 : PyRef( PyObject * p ) : m( p ) { Py_XINCREF( m ); }
95 :
96 4940 : PyRef( PyObject * p, __sal_NoAcquire ) : m( p ) {}
97 :
98 1076 : PyRef( PyObject * p, __sal_NoAcquire, __NotNull ) : m( p )
99 : {
100 1076 : if (!m)
101 0 : throw std::bad_alloc();
102 1076 : }
103 :
104 1624 : PyRef( const PyRef &r ) : m( r.get() ) { Py_XINCREF( m ); }
105 :
106 37278 : ~PyRef() { Py_XDECREF( m ); }
107 :
108 31654 : PyObject *get() const { return m; }
109 :
110 19334 : PyObject * getAcquired() const
111 : {
112 19334 : Py_XINCREF( const_cast< PyObject*> (m) );
113 19334 : return m;
114 : }
115 :
116 15348 : PyRef & operator = ( const PyRef & r )
117 : {
118 15348 : PyObject *tmp = m;
119 15348 : m = r.getAcquired();
120 15348 : Py_XDECREF( tmp );
121 15348 : return *this;
122 : }
123 :
124 28 : bool operator == ( const PyRef & r ) const
125 : {
126 28 : return r.get() == m;
127 : }
128 :
129 : /** clears the reference without decreasing the reference count
130 : only seldomly needed ! */
131 8 : void scratch()
132 : {
133 8 : m = 0;
134 8 : }
135 :
136 : /** clears the reference decreasing the refcount of the holded object.
137 : */
138 : void clear()
139 : {
140 : Py_XDECREF( m );
141 : m = 0;
142 : }
143 :
144 : /** returns 1 when the reference points to a python object python object,
145 : otherwise 0.
146 : */
147 13004 : bool is() const
148 : {
149 13004 : return m != 0;
150 : }
151 :
152 : struct Hash
153 : {
154 116 : sal_IntPtr operator () ( const PyRef &r) const { return sal_IntPtr( r.get() ); }
155 : };
156 : };
157 :
158 : struct stRuntimeImpl;
159 : typedef struct stRuntimeImpl RuntimeImpl;
160 :
161 : enum ConversionMode { ACCEPT_UNO_ANY, REJECT_UNO_ANY };
162 :
163 :
164 : /** The pyuno::Runtime class keeps the internal state of the python UNO bridge
165 : for the currently in use python interpreter.
166 :
167 : You may keep a Runtime instance, use it from a different thread, etc. But you must
168 : make sure to fulfill all preconditions mentioned for the specific methods.
169 : */
170 :
171 : class LO_DLLPUBLIC_PYUNO Runtime
172 : {
173 : RuntimeImpl *impl;
174 : public:
175 : ~Runtime( );
176 :
177 : /**
178 : preconditions: python has been initialized before,
179 : the global interpreter lock is held and pyuno
180 : has been initialized for the currently used interpreter.
181 :
182 : Note: This method exists for efficiency reasons to save
183 : lookup costs for any2PyObject and pyObject2Any
184 :
185 : @throw RuntimeException in case the runtime has not been
186 : initialized before
187 : */
188 : Runtime() throw( com::sun::star::uno::RuntimeException );
189 :
190 : Runtime( const Runtime & );
191 : Runtime & operator = ( const Runtime & );
192 :
193 : /** Initializes the python-UNO bridge. May be called only once per python interpreter.
194 :
195 : @param ctx the component context is used to instantiate bridge services needed
196 : for bridging such as invocation, typeconverter, invocationadapterfactory, etc.
197 :
198 : preconditions: python has been initialized before and
199 : the global interpreter lock is held and pyuno is not
200 : initialized (see isInitialized() ).
201 :
202 : @throw RuntimeException in case the thread is not attached or the runtime
203 : has not been initialized.
204 : */
205 : static void SAL_CALL initialize(
206 : const com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > & ctx )
207 : throw ( com::sun::star::uno::RuntimeException );
208 :
209 : /** Checks, whether the uno runtime is already initialized in the current python interpreter.
210 : */
211 : static bool SAL_CALL isInitialized() throw (com::sun::star::uno::RuntimeException);
212 :
213 : /** converts something contained in an UNO Any to a Python object
214 :
215 : preconditions: python has been initialized before,
216 : the global interpreter lock is held and pyuno::Runtime
217 : has been initialized.
218 : */
219 : PyRef any2PyObject (const com::sun::star::uno::Any &source ) const
220 : throw ( com::sun::star::script::CannotConvertException,
221 : com::sun::star::lang::IllegalArgumentException,
222 : com::sun::star::uno::RuntimeException );
223 :
224 : /** converts a Python object to a UNO any
225 :
226 : preconditions: python has been initialized before,
227 : the global interpreter lock is held and pyuno
228 : has been initialized
229 : */
230 : com::sun::star::uno::Any pyObject2Any (
231 : const PyRef & source , enum ConversionMode mode = REJECT_UNO_ANY ) const
232 : throw ( com::sun::star::uno::RuntimeException);
233 :
234 : /** extracts a proper uno exception from a given python exception
235 : */
236 : com::sun::star::uno::Any extractUnoException(
237 : const PyRef & excType, const PyRef & excValue, const PyRef & excTraceback) const;
238 :
239 : /** Returns the internal handle. Should only be used by the module implementation
240 : */
241 5530 : RuntimeImpl *getImpl() const { return impl; }
242 : };
243 :
244 :
245 : /** helper class for attaching the current thread to the python runtime.
246 :
247 : Attaching is done creating a new threadstate for the given interpreter
248 : and acquiring the global interpreter lock.
249 :
250 : Usage:
251 :
252 : ... don't use python here
253 : {
254 : PyThreadAttach guard( PyInterpreterState_Head() );
255 : {
256 : ... do whatever python code you want
257 : {
258 : PyThreadDetach antiguard;
259 : ... don't use python here
260 : }
261 : ... do whatever python code you want
262 : }
263 : }
264 : ... don't use python here
265 :
266 : Note: The additional scope brackets after the PyThreadAttach are needed,
267 : e.g. when you would leave them away, dtors of potential pyrefs
268 : may be called after the thread has detached again.
269 : */
270 : class LO_DLLPUBLIC_PYUNO PyThreadAttach
271 : {
272 : PyThreadState *tstate;
273 : PyThreadAttach ( const PyThreadAttach & ); // not implemented
274 : PyThreadAttach & operator = ( const PyThreadAttach & );
275 : public:
276 :
277 : /** Creates a new python threadstate and acquires the global interpreter lock.
278 : precondition: The current thread MUST NOT hold the global interpreter lock.
279 : postcondition: The global interpreter lock is acquired
280 :
281 : @raises com::sun::star::uno::RuntimeException
282 : in case no pythread state could be created
283 : */
284 : PyThreadAttach( PyInterpreterState *interp) throw ( com::sun::star::uno::RuntimeException );
285 :
286 :
287 : /** Releases the global interpreter lock and destroys the thread state.
288 : */
289 : ~PyThreadAttach();
290 : };
291 :
292 : /** helper class for detaching the current thread from the python runtime
293 : to do some blocking, non-python related operation.
294 :
295 : @see PyThreadAttach
296 : */
297 : class LO_DLLPUBLIC_PYUNO PyThreadDetach
298 : {
299 : PyThreadState *tstate;
300 : PyThreadDetach ( const PyThreadDetach & ); // not implemented
301 : PyThreadDetach & operator = ( const PyThreadDetach & ); // not implemented
302 :
303 : public:
304 : /** Releases the global interpreter lock.
305 :
306 : precondition: The current thread MUST hold the global interpreter lock.
307 : postcondition: The current thread does not hold the global interpreter lock anymore.
308 : */
309 : PyThreadDetach() throw ( com::sun::star::uno::RuntimeException );
310 : /** Acquires the global interpreter lock again
311 : */
312 : ~PyThreadDetach();
313 : };
314 :
315 : }
316 : #endif
317 :
318 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|