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