20#include <config_features.h>
21#include <config_folders.h>
28#include <osl/process.h>
29#include <osl/file.hxx>
30#include <osl/thread.h>
32#include <rtl/ustrbuf.hxx>
33#include <rtl/bootstrap.hxx>
37#include <com/sun/star/uno/XComponentContext.hpp>
42#define PATH_MAX _MAX_PATH
45#define PATH_MAX MAX_PATH
58using com::sun::star::uno::XInterface;
60using com::sun::star::uno::XComponentContext;
61using com::sun::star::uno::RuntimeException;
69 if( PyErr_Occurred() )
71 PyRef excType, excValue, excTraceback;
72 PyErr_Fetch(
reinterpret_cast<PyObject **
>(&excType),
reinterpret_cast<PyObject**
>(&excValue),
reinterpret_cast<PyObject**
>(&excTraceback));
75 OUStringBuffer buf(
"python-loader:" );
76 if(
auto e = o3tl::tryAccess<css::uno::Exception>(
a) )
77 buf.append( e->Message );
86 PyImport_ImportModule(
"pythonloader" ),
102 throw RuntimeException(
"pythonloader: couldn't find core element pythonloader." +
103 OUString::createFromAscii( func ));
110 OUString systemPythonHome;
111 osl_getSystemPathFromFileURL( pythonHome.pData, &(systemPythonHome.pData) );
113 static wchar_t wide[PATH_MAX + 1];
115 const size_t len = systemPythonHome.getLength();
116 if (len < std::size(wide))
117 wcsncpy(wide, o3tl::toW(systemPythonHome.getStr()), len + 1);
120 size_t len = mbstowcs(wide, o.pData->buffer, PATH_MAX + 1);
121 if(len ==
size_t(-1))
123 PyErr_SetString(PyExc_SystemError,
"invalid multibyte sequence in python home path");
127 if(len >= PATH_MAX + 1)
129 PyErr_SetString(PyExc_SystemError,
"python home path is too long");
133 Py_SetPythonHome(wide);
139 OUStringBuffer bufPYTHONPATH( 256 );
140 bool bAppendSep =
false;
144 size_t nNew = pythonPathBootstrap.find(
' ',
nIndex );
145 std::u16string_view fileUrl;
146 if( nNew == std::u16string_view::npos )
148 fileUrl = pythonPathBootstrap.substr(
nIndex);
152 fileUrl = pythonPathBootstrap.substr(
nIndex, nNew -
nIndex);
155 osl_getSystemPathFromFileURL( OUString(fileUrl).
pData, &(systemPath.pData) );
156 if (!systemPath.isEmpty())
160 bufPYTHONPATH.append(systemPath);
163 if( nNew == std::u16string_view::npos )
167 const char * oldEnv = getenv(
"PYTHONPATH");
172 bufPYTHONPATH.append( OUString(oldEnv, strlen(oldEnv), osl_getThreadTextEncoding()) );
175 OUString envVar(
"PYTHONPATH");
176 OUString envValue(bufPYTHONPATH.makeStringAndClear());
177 osl_setEnvironment(envVar.pData, envValue.pData);
183 if ( Py_IsInitialized())
188 OUString path(
"$BRAND_BASE_DIR/" LIBO_ETC_FOLDER
"/" SAL_CONFIGFILE(
"pythonloader.uno" ));
189 rtl::Bootstrap::expandMacros(path);
193 bootstrap.getFrom(
"PYUNO_LOADER_PYTHONHOME", pythonHome );
194 bootstrap.getFrom(
"PYUNO_LOADER_PYTHONPATH", pythonPath );
198 if( !pythonHome.isEmpty() )
201 if( !pythonPath.isEmpty() )
207 OUString sEnvName(
"PATH");
209 osl_getEnvironment(sEnvName.pData, &sPath.pData);
210 OUString sBrandLocation(
"$BRAND_BASE_DIR/program");
211 rtl::Bootstrap::expandMacros(sBrandLocation);
212 osl::FileBase::getSystemPathFromFileURL(sBrandLocation, sBrandLocation);
213 sPath = sPath + OUStringChar(SAL_PATHSEPARATOR) + sBrandLocation;
214 osl_setEnvironment(sEnvName.pData, sPath.pData);
219#if HAVE_FEATURE_READONLY_INSTALLSET
220 Py_DontWriteBytecodeFlag = 1;
225#if PY_VERSION_HEX < 0x03090000
226 PyEval_InitThreads();
229 PyThreadState *tstate = PyThreadState_Get();
230 PyEval_ReleaseThread( tstate );
231#if PY_VERSION_HEX < 0x030B0000
235 PyThreadState_Delete(tstate);
241extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
243 css::uno::XComponentContext* ctx , css::uno::Sequence<css::uno::Any>
const&)
256 if( ! Runtime::isInitialized() )
258 Runtime::initialize(
ctx );
263 css::uno::Any( css::uno::Reference(
ctx) ) );
268 PyRef pyInstance( PyObject_CallObject( clazz.
get() ,
args.get() ), SAL_NO_ACQUIRE );
Helper class for keeping references to python objects.
PyObject * get() const noexcept
PyObject * getAcquired() const
helper class for attaching the current thread to the python runtime.
The pyuno::Runtime class keeps the internal state of the python UNO bridge for the currently in use p...
css::uno::Any extractUnoException(const PyRef &excType, const PyRef &excValue, const PyRef &excTraceback) const
extracts a proper uno exception from a given python exception
css::uno::Any pyObject2Any(const PyRef &source, enum ConversionMode mode=REJECT_UNO_ANY) const
converts a Python object to a UNO any
PyRef any2PyObject(const css::uno::Any &source) const
converts something contained in a UNO Any to a Python object
#define SAL_PATHSEPARATOR
#define SAL_CONFIGFILE(name)
std::unique_ptr< sal_Int32[]> pData
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
static PyRef getLoaderModule()
static PyRef getObjectFromLoaderModule(const char *func)
static void prependPythonPath(std::u16string_view pythonPathBootstrap)
static void raiseRuntimeExceptionWhenNeeded()
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * pyuno_Loader_get_implementation(css::uno::XComponentContext *ctx, css::uno::Sequence< css::uno::Any > const &)
static void setPythonHome(const OUString &pythonHome)
@ NOT_NULL
definition of a no acquire enum for ctors
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
SAL_DLLPUBLIC_EXPORT PyObject * PyInit_pyuno(void)
function called by the python runtime to initialize the pyuno module.
#define SAL_WNODEPRECATED_DECLARATIONS_POP
#define SAL_WNODEPRECATED_DECLARATIONS_PUSH