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