summaryrefslogtreecommitdiffstats
path: root/pyuno/inc
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /pyuno/inc
parentInitial commit. (diff)
downloadlibreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz
libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'pyuno/inc')
-rw-r--r--pyuno/inc/pyuno.hxx321
1 files changed, 321 insertions, 0 deletions
diff --git a/pyuno/inc/pyuno.hxx b/pyuno/inc/pyuno.hxx
new file mode 100644
index 000000000..f7cab36c7
--- /dev/null
+++ b/pyuno/inc/pyuno.hxx
@@ -0,0 +1,321 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * 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 .
+ */
+
+#pragma once
+
+#ifndef Py_PYTHON_H
+#include <Python.h>
+#endif // #ifdef Py_PYTHON_H
+
+#include <com/sun/star/uno/Any.hxx>
+
+namespace com::sun::star::uno { class XComponentContext; }
+namespace com::sun::star::uno { template <typename > class Reference; }
+
+/**
+ 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.
+*/
+
+#if defined LO_DLLIMPLEMENTATION_PYUNO
+#define LO_DLLPUBLIC_PYUNO SAL_DLLPUBLIC_EXPORT
+#else
+#define LO_DLLPUBLIC_PYUNO SAL_DLLPUBLIC_IMPORT
+#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" LO_DLLPUBLIC_PYUNO PyObject* PyInit_pyuno();
+
+namespace pyuno
+{
+
+enum NotNull
+{
+ /** definition of a no acquire enum for ctors
+ */
+ NOT_NULL
+};
+
+/** Helper class for keeping references to python objects.
+ BEWARE: Look up every python function you use to check
+ whether 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(nullptr) {}
+ PyRef( PyObject * p ) : m( p ) { Py_XINCREF( m ); }
+
+ PyRef( PyObject * p, __sal_NoAcquire ) : m( p ) {}
+
+ PyRef( PyObject * p, __sal_NoAcquire, NotNull ) : m( p )
+ {
+ if (!m)
+ throw std::bad_alloc();
+ }
+
+ PyRef(const PyRef &r) : m(r.get()) { Py_XINCREF(m); }
+ PyRef(PyRef &&r) noexcept : m(r.get()) { r.scratch(); }
+
+ ~PyRef() { Py_XDECREF( m ); }
+
+ PyObject *get() const noexcept { return m; }
+
+ PyObject * getAcquired() const
+ {
+ Py_XINCREF( m );
+ return m;
+ }
+
+ PyRef& operator=(const PyRef& r)
+ {
+ PyObject *tmp = m;
+ m = r.getAcquired();
+ Py_XDECREF(tmp);
+ return *this;
+ }
+
+ PyRef& operator=(PyRef&& r)
+ {
+ PyObject *tmp = m;
+ m = r.get();
+ r.scratch();
+ Py_XDECREF(tmp);
+ return *this;
+ }
+
+ bool operator == ( const PyRef & r ) const
+ {
+ return r.get() == m;
+ }
+
+ /** clears the reference without decreasing the reference count
+ only seldom needed ! */
+ void scratch() noexcept
+ {
+ m = nullptr;
+ }
+
+ /** returns 1 when the reference points to a python object python object,
+ otherwise 0.
+ */
+ bool is() const
+ {
+ return m != nullptr;
+ }
+
+ struct Hash
+ {
+ sal_IntPtr operator () ( const PyRef &r) const { return reinterpret_cast<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 LO_DLLPUBLIC_PYUNO Runtime
+{
+ RuntimeImpl *impl;
+
+ /**
+ Safely unpacks a Python iterator into a sequence, then
+ stores it in an Any. Used internally by pyObject2Any
+ */
+ bool pyIterUnpack( PyObject *const, css::uno::Any & ) const;
+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();
+
+ 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 initialize(
+ const css::uno::Reference< css::uno::XComponentContext > & ctx );
+
+ /** Checks, whether the uno runtime is already initialized in the current python interpreter.
+
+ @throws css::uno::RuntimeException
+ */
+ static bool isInitialized();
+
+ /** converts something contained in a UNO Any to a Python object
+
+ preconditions: python has been initialized before,
+ the global interpreter lock is held and pyuno::Runtime
+ has been initialized.
+
+ @throws css::script::CannotConvertException
+ @throws css::lang::IllegalArgumentException
+ @throws css::uno::RuntimeException
+ */
+ PyRef any2PyObject (const css::uno::Any &source ) const;
+
+ /** 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
+
+ @throws css::uno::RuntimeException
+ */
+ css::uno::Any pyObject2Any (
+ const PyRef & source , enum ConversionMode mode = REJECT_UNO_ANY ) const;
+
+ /** extracts a proper uno exception from a given python exception
+ */
+ css::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 LO_DLLPUBLIC_PYUNO PyThreadAttach
+{
+ PyThreadState *tstate;
+ bool m_isNewState;
+ PyThreadAttach ( const PyThreadAttach & ) = delete;
+ PyThreadAttach & operator = ( const PyThreadAttach & ) = delete;
+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
+
+ @throws css::uno::RuntimeException
+ in case no pythread state could be created
+ */
+ PyThreadAttach( PyInterpreterState *interp);
+
+
+ /** 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 PyThreadDetach
+{
+ PyThreadState *tstate;
+ PyThreadDetach ( const PyThreadDetach & ) = delete;
+ PyThreadDetach & operator = ( const PyThreadDetach & ) = delete;
+
+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.
+
+ @throws css::uno::RuntimeException
+ */
+ PyThreadDetach();
+ /** Acquires the global interpreter lock again
+ */
+ ~PyThreadDetach();
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */