blob: b6ccf3cd129593911fa087d2083ceb0c3ee212f6 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#ifndef _PYUNO_PYUNO_HXX_
#define _PYUNO_PYUNO_HXX_
#ifndef Py_PYTHON_H
#if defined _MSC_VER
#pragma warning(push, 1)
#endif
#ifdef _DEBUG
#undef _DEBUG
#include <Python.h>
#define _DEBUG
#else
#include <Python.h>
#endif // #ifdef _DEBUG
#if defined _MSC_VER
#pragma warning(pop)
#endif
#endif // #ifdef Py_PYTHON_H
// Compatibility for older system Python (2.6 and previous)
#ifndef PyVarObject_HEAD_INIT
#define PyVarObject_HEAD_INIT(type, size) \
PyObject_HEAD_INIT(type) size,
#endif
// define PyBytes_* as the equivalent string type methods.
#ifndef PyBytes_Check
#define PyBytes_Check PyString_Check
#define PyBytes_AsString PyString_AsString
#define PyBytes_FromString PyString_FromString
#define PyBytes_Size PyString_Size
#define PyBytes_FromStringAndSize PyString_FromStringAndSize
#endif
#include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/script/CannotConvertException.hpp>
#include <com/sun/star/lang/IllegalArgumentException.hpp>
/**
External interface of the Python UNO bridge.
This is a C++ interface, because the core UNO components
invocation and proxyfactory are used to implement the bridge.
This interface is somewhat private and my change in future.
A scripting framework implementation may use this interface
to do the necessary conversions.
*/
#ifdef WIN32
#define PY_DLLEXPORT __declspec(dllexport)
#else
#define PY_DLLEXPORT
#endif
/** function called by the python runtime to initialize the
pyuno module.
preconditions: python has been initialized before and
the global interpreter lock is held
*/
extern "C" PY_DLLEXPORT void SAL_CALL initpyuno();
namespace pyuno
{
/** Helper class for keeping references to python objects.
BEWARE: Look up every python function you use to check
wether you get an acquired or not acquired object pointer
(python terminus for a not acquired object pointer
is 'borrowed reference'). Use in the acquired pointer cases the
PyRef( pointer, SAL_NO_ACQUIRE) ctor.
precondition: python has been initialized before and
the global interpreter lock is held
*/
class PyRef
{
PyObject *m;
public:
PyRef () : m(0) {}
PyRef( PyObject * p ) : m( p ) { Py_XINCREF( m ); }
PyRef( PyObject * p, __sal_NoAcquire ) : m( p ) {}
PyRef( const PyRef &r ) : m( r.get() ) { Py_XINCREF( m ); }
~PyRef() { Py_XDECREF( m ); }
PyObject *get() const { return m; }
PyObject * getAcquired() const
{
Py_XINCREF( const_cast< PyObject*> (m) );
return m;
}
PyRef & operator = ( const PyRef & r )
{
PyObject *tmp = m;
m = r.getAcquired();
Py_XDECREF( tmp );
return *this;
}
bool operator == ( const PyRef & r ) const
{
return r.get() == m;
}
/** clears the reference without decreasing the reference count
only seldomly needed ! */
void scratch()
{
m = 0;
}
/** clears the reference decreasing the refcount of the holded object.
*/
void clear()
{
Py_XDECREF( m );
m = 0;
}
/** returns 1 when the reference points to a python object python object,
otherwise 0.
*/
sal_Bool is() const
{
return m != 0;
}
struct Hash
{
sal_IntPtr operator () ( const PyRef &r) const { return sal_IntPtr( r.get() ); }
};
};
struct stRuntimeImpl;
typedef struct stRuntimeImpl RuntimeImpl;
enum ConversionMode { ACCEPT_UNO_ANY, REJECT_UNO_ANY };
/** The pyuno::Runtime class keeps the internal state of the python UNO bridge
for the currently in use python interpreter.
You may keep a Runtime instance, use it from a different thread, etc. But you must
make sure to fulfill all preconditions mentioned for the specific methods.
*/
class PY_DLLEXPORT Runtime
{
RuntimeImpl *impl;
public:
~Runtime( );
/**
preconditions: python has been initialized before,
the global interpreter lock is held and pyuno
has been initialized for the currently used interpreter.
Note: This method exists for efficiency reasons to save
lookup costs for any2PyObject and pyObject2Any
@throw RuntimeException in case the runtime has not been
initialized before
*/
Runtime() throw( com::sun::star::uno::RuntimeException );
Runtime( const Runtime & );
Runtime & operator = ( const Runtime & );
/** Initializes the python-UNO bridge. May be called only once per python interpreter.
@param ctx the component context is used to instantiate bridge services needed
for bridging such as invocation, typeconverter, invocationadapterfactory, etc.
preconditions: python has been initialized before and
the global interpreter lock is held and pyuno is not
initialized (see isInitialized() ).
@throw RuntimeException in case the thread is not attached or the runtime
has not been initialized.
*/
static void SAL_CALL initialize(
const com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > & ctx )
throw ( com::sun::star::uno::RuntimeException );
/** Checks, whether the uno runtime is already initialized in the current python interpreter.
*/
static bool SAL_CALL isInitialized() throw (com::sun::star::uno::RuntimeException);
/** disposes the UNO bridge in this interpreter. All existing stubs/proxies
become non-functional, using these proxies/stubs leads to runtime errors.
preconditions: python has been initialized before and
the global interpreter lock is held and pyuno was
initialized before for the currently in use interpreter.
*/
static void SAL_CALL finalize() throw(com::sun::star::uno::RuntimeException );
/** converts something contained in an UNO Any to a Python object
preconditions: python has been initialized before,
the global interpreter lock is held and pyuno::Runtime
has been initialized.
*/
PyRef any2PyObject (const com::sun::star::uno::Any &source ) const
throw ( com::sun::star::script::CannotConvertException,
com::sun::star::lang::IllegalArgumentException,
com::sun::star::uno::RuntimeException );
/** converts a Python object to a UNO any
preconditions: python has been initialized before,
the global interpreter lock is held and pyuno
has been initialized
*/
com::sun::star::uno::Any pyObject2Any (
const PyRef & source , enum ConversionMode mode = REJECT_UNO_ANY ) const
throw ( com::sun::star::uno::RuntimeException);
/** extracts a proper uno exception from a given python exception
*/
com::sun::star::uno::Any extractUnoException(
const PyRef & excType, const PyRef & excValue, const PyRef & excTraceback) const;
/** Returns the internal handle. Should only be used by the module implementation
*/
RuntimeImpl *getImpl() const { return impl; }
};
/** helper class for attaching the current thread to the python runtime.
Attaching is done creating a new threadstate for the given interpreter
and acquiring the global interpreter lock.
Usage:
... don't use python here
{
PyThreadAttach guard( PyInterpreterState_Head() );
{
... do whatever python code you want
{
PyThreadDetach antiguard;
... don't use python here
}
... do whatever python code you want
}
}
... don't use python here
Note: The additional scope brackets after the PyThreadAttach are needed,
e.g. when you would leave them away, dtors of potential pyrefs
may be called after the thread has detached again.
*/
class PY_DLLEXPORT PyThreadAttach
{
PyThreadState *tstate;
PyThreadAttach ( const PyThreadAttach & ); // not implemented
PyThreadAttach & operator = ( const PyThreadAttach & );
public:
/** Creates a new python threadstate and acquires the global interpreter lock.
precondition: The current thread MUST NOT hold the global interpreter lock.
postcondition: The global interpreter lock is acquired
@raises com::sun::star::uno::RuntimeException
in case no pythread state could be created
*/
PyThreadAttach( PyInterpreterState *interp) throw ( com::sun::star::uno::RuntimeException );
/** Releases the global interpreter lock and destroys the thread state.
*/
~PyThreadAttach();
};
/** helper class for detaching the current thread from the python runtime
to do some blocking, non-python related operation.
@see PyThreadAttach
*/
class PY_DLLEXPORT PyThreadDetach
{
PyThreadState *tstate;
PyThreadDetach ( const PyThreadDetach & ); // not implemented
PyThreadDetach & operator = ( const PyThreadDetach & ); // not implemented
public:
/** Releases the global interpreter lock.
precondition: The current thread MUST hold the global interpreter lock.
postcondition: The current thread does not hold the global interpreter lock anymore.
*/
PyThreadDetach() throw ( com::sun::star::uno::RuntimeException );
/** Acquires the global interpreter lock again
*/
~PyThreadDetach();
};
}
#endif