20#include <config_folders.h> 
   26#include <unordered_map> 
   28#include <osl/module.hxx> 
   29#include <osl/thread.h> 
   30#include <osl/file.hxx> 
   33#include <typelib/typedescription.hxx> 
   35#include <rtl/ustring.hxx> 
   36#include <rtl/strbuf.hxx> 
   37#include <rtl/ustrbuf.hxx> 
   39#include <rtl/bootstrap.hxx> 
   41#include <uno/current_context.hxx> 
   44#include <com/sun/star/lang/XMultiServiceFactory.hpp> 
   45#include <com/sun/star/reflection/XConstantTypeDescription.hpp> 
   46#include <com/sun/star/reflection/XIdlClass.hpp> 
   47#include <com/sun/star/registry/InvalidRegistryException.hpp> 
   48#include <com/sun/star/script/CannotConvertException.hpp> 
   49#include <com/sun/star/uno/XComponentContext.hpp> 
   50#include <com/sun/star/script/XInvocation2.hpp> 
   51#include <com/sun/star/reflection/XIdlReflection.hpp> 
   52#include <com/sun/star/container/XHierarchicalNameAccess.hpp> 
   59using com::sun::star::uno::Any;
 
   60using com::sun::star::uno::RuntimeException;
 
   61using com::sun::star::uno::TypeDescription;
 
   62using com::sun::star::uno::XComponentContext;
 
   63using com::sun::star::container::NoSuchElementException;
 
   64using com::sun::star::reflection::XIdlClass;
 
   65using com::sun::star::script::XInvocation2;
 
   88    std::unordered_map <OUString, bool> initialised;
 
   91    sal_Int32 nPosConsumed;
 
   99            throw RuntimeException(
"pyuno._createUnoStructHelper failed to create new dictionary");
 
  105    void setUsed(PyObject *key)
 
  107        PyDict_SetItem(used, key, Py_True);
 
  109    void setInitialised(
const OUString& key, sal_Int32 pos = -1)
 
  111        if (initialised[key])
 
  113            OUStringBuffer buf( 
"pyuno._createUnoStructHelper: member '" + key + 
"'");
 
  116                buf.append( 
" at position " + OUString::number(pos));
 
  118            buf.append( 
" initialised multiple times.");
 
  119            throw RuntimeException(buf.makeStringAndClear());
 
  121        initialised[key] = 
true;
 
  125    bool isInitialised(
const OUString& key)
 
  127        return initialised[key];
 
  129    PyObject *getUsed()
 const 
  133    sal_Int32 getCntConsumed()
 const 
  142    typelib_CompoundTypeDescription *pCompType,
 
  143    PyObject *initializer,
 
  144    PyObject *kwinitializer,
 
  145    fillStructState &state,
 
  148    if( pCompType->pBaseTypeDescription )
 
  149        fillStruct( inv, pCompType->pBaseTypeDescription, initializer, kwinitializer, state, runtime );
 
  151    const sal_Int32 nMembers = pCompType->nMembers;
 
  153        for( 
int i = 0 ; 
i < nMembers ; 
i ++ )
 
  155            const OUString OUMemberName (pCompType->ppMemberNames[i]);
 
  156            PyObject *pyMemberName =
 
  158                        RTL_TEXTENCODING_UTF8).getStr());
 
  159            if ( PyObject *element = PyDict_GetItem(kwinitializer, pyMemberName ) )
 
  161                state.setInitialised(OUMemberName);
 
  162                state.setUsed(pyMemberName);
 
  164                inv->setValue( OUMemberName, a );
 
  169        const int remainingPosInitialisers = PyTuple_Size(initializer) - state.getCntConsumed();
 
  170        for( 
int i = 0 ; 
i < remainingPosInitialisers && 
i < nMembers ; 
i ++ )
 
  172            const int tupleIndex = state.getCntConsumed();
 
  173            const OUString& rMemberName (pCompType->ppMemberNames[i]);
 
  174            state.setInitialised(rMemberName, tupleIndex);
 
  175            PyObject *element = PyTuple_GetItem( initializer, tupleIndex );
 
  177            inv->setValue( rMemberName, a );
 
  180    if ( PyTuple_Size( initializer ) <= 0 )
 
  184    for ( 
int i = 0; 
i < nMembers ; ++
i)
 
  186        const OUString memberName (pCompType->ppMemberNames[i]);
 
  187        if ( ! state.isInitialised( memberName ) )
 
  189            OUString buf = 
"pyuno._createUnoStructHelper: member '" +
 
  191                "' of struct type '" +
 
  192                OUString::unacquired(&pCompType->aBase.pTypeName) +
 
  193                "' not given a value.";
 
  194            throw RuntimeException(buf);
 
  201    static OUString sLibDir = []() {
 
  205        if (Module::getUrlFromAddress(
reinterpret_cast<oslGenericFunction
>(getLibDir), libDir))
 
  207            libDir = libDir.copy(0, libDir.lastIndexOf(
'/'));
 
  208            OUString 
name(
"PYUNOLIBDIR");
 
  209            rtl_bootstrap_set(
name.pData, libDir.pData);
 
  217void raisePySystemException( 
const char * exceptionType, std::u16string_view message )
 
  219    OString buf = OString::Concat(
"Error during bootstrapping uno (") +
 
  223    PyErr_SetString( PyExc_SystemError, buf.getStr() );
 
  229    SAL_UNUSED_PARAMETER PyObject*, SAL_UNUSED_PARAMETER PyObject*)
 
  237        OUString path( getLibDir());
 
  238        if( Runtime::isInitialized() )
 
  248                    PyExc_RuntimeError, 
"osl_getUrlFromAddress fails, that's why I cannot find ini " 
  249                    "file for bootstrapping python uno bridge\n" );
 
  253            OUString iniFile = path +
 
  255                    "/../" LIBO_ETC_FOLDER
 
  258            osl::DirectoryItem item;
 
  259            if( osl::DirectoryItem::get( iniFile, item ) == osl::FileBase::E_None )
 
  274        if( ! Runtime::isInitialized() )
 
  276            Runtime::initialize( ctx );
 
  281    catch (
const css::registry::InvalidRegistryException &e)
 
  286        raisePySystemException( 
"InvalidRegistryException", e.Message );
 
  288    catch(
const css::lang::IllegalArgumentException & e)
 
  290        raisePySystemException( 
"IllegalArgumentException", e.Message );
 
  292    catch(
const css::script::CannotConvertException & e)
 
  294        raisePySystemException( 
"CannotConvertException", e.Message );
 
  296    catch (
const css::uno::RuntimeException & e)
 
  298        raisePySystemException( 
"RuntimeException", e.Message );
 
  300    catch (
const css::uno::Exception & e)
 
  302        raisePySystemException( 
"uno::Exception", e.Message );
 
  314osl::Module * testModule = 
nullptr;
 
  316static PyObject* initTestEnvironment(
 
  317    SAL_UNUSED_PARAMETER PyObject*, SAL_UNUSED_PARAMETER PyObject*)
 
  322    assert(testModule == 
nullptr);
 
  326        if (!ctx) { abort(); }
 
  331        if (!xContext.is()) { abort(); }
 
  332        using css::lang::XMultiServiceFactory;
 
  334            xContext->getServiceManager(),
 
  335            css::uno::UNO_QUERY_THROW);
 
  336        char *
const testlib = getenv(
"TEST_LIB");
 
  337        if (!testlib) { abort(); }
 
  339        OString 
const libname = OString(testlib, strlen(testlib))
 
  340            .replaceAll(OString(
'/'), OString(
'\\'));
 
  342        OString 
const libname(testlib, strlen(testlib));
 
  346        mod.load(OStringToOUString(libname, osl_getThreadTextEncoding()),
 
  347                                SAL_LOADMODULE_LAZY | SAL_LOADMODULE_GLOBAL);
 
  348        if (!mod.is()) { abort(); }
 
  349        oslGenericFunction 
const pFunc(
 
  350                mod.getFunctionSymbol(
"test_init"));
 
  351        if (!pFunc) { abort(); }
 
  352        reinterpret_cast<void (SAL_CALL *)(XMultiServiceFactory*)
>(pFunc)(xMSF.get());
 
  355    catch (
const css::uno::Exception &)
 
  362static PyObject* deinitTestEnvironment(
 
  363    SAL_UNUSED_PARAMETER PyObject*, SAL_UNUSED_PARAMETER PyObject*)
 
  365    if (testModule != 
nullptr)
 
  369            oslGenericFunction 
const pFunc(
 
  370                    testModule->getFunctionSymbol(
"test_deinit"));
 
  371            if (!pFunc) { abort(); }
 
  372            reinterpret_cast<void (SAL_CALL *)()
>(pFunc)();
 
  374        catch (
const css::uno::Exception &)
 
  382PyObject * extractOneStringArg( PyObject *args, 
char const *funcName )
 
  384    if( !PyTuple_Check( args ) || PyTuple_Size( args) != 1 )
 
  386        OString buf = funcName + OString::Concat(
": expecting one string argument");
 
  387        PyErr_SetString( PyExc_RuntimeError, buf.getStr() );
 
  390    PyObject *obj = PyTuple_GetItem( args, 0 );
 
  391    if (!PyUnicode_Check(obj))
 
  393        OString buf = funcName + OString::Concat(
": expecting one string argument");
 
  394        PyErr_SetString( PyExc_TypeError, buf.getStr());
 
  400static PyObject *createUnoStructHelper(
 
  401    SAL_UNUSED_PARAMETER PyObject *, PyObject* args, PyObject* keywordArgs)
 
  408        if( PyTuple_Size( args ) == 2 )
 
  410            PyObject *structName = PyTuple_GetItem(args, 0);
 
  411            PyObject *initializer = PyTuple_GetItem(args, 1);
 
  413            if (PyUnicode_Check(structName))
 
  415                if( PyTuple_Check( initializer ) && PyDict_Check ( keywordArgs ) )
 
  417                    OUString 
typeName( OUString::createFromAscii(PyUnicode_AsUTF8(structName)));
 
  422                        idl_class->createObject (IdlStruct);
 
  424                        PyUNO *me = 
reinterpret_cast<PyUNO*
>( returnCandidate.get() );
 
  425                        TypeDescription desc( typeName );
 
  426                        OSL_ASSERT( desc.is() ); 
 
  428                        typelib_CompoundTypeDescription *pCompType =
 
  429                            reinterpret_cast<typelib_CompoundTypeDescription *
>(desc.get());
 
  430                        fillStructState state;
 
  431                        if ( PyTuple_Size( initializer ) > 0 || PyDict_Size( keywordArgs ) > 0 )
 
  433                        if( state.getCntConsumed() != PyTuple_Size(initializer) )
 
  435                            throw RuntimeException( 
"pyuno._createUnoStructHelper: too many " 
  436                                "elements in the initializer list, expected " +
 
  437                                OUString::number(state.getCntConsumed()) + 
", got " +
 
  438                                OUString::number( PyTuple_Size(initializer) ) );
 
  440                        ret = 
PyRef( PyTuple_Pack(2, returnCandidate.get(), state.getUsed()), SAL_NO_ACQUIRE);
 
  444                        OString buf = OString::Concat(
"UNO struct ")
 
  445                            + PyUnicode_AsUTF8(structName)
 
  447                        PyErr_SetString (PyExc_RuntimeError, buf.getStr());
 
  454                        "pyuno._createUnoStructHelper: 2nd argument (initializer sequence) is no tuple" );
 
  459                PyErr_SetString (PyExc_AttributeError, 
"createUnoStruct: first argument wasn't a string");
 
  464            PyErr_SetString (PyExc_AttributeError, 
"pyuno._createUnoStructHelper: expects exactly two non-keyword arguments:\n\tStructure Name\n\tinitialiser tuple; may be the empty tuple");
 
  467    catch( 
const css::uno::RuntimeException & e )
 
  471    catch( 
const css::script::CannotConvertException & e )
 
  475    catch( 
const css::uno::Exception & e )
 
  483    SAL_UNUSED_PARAMETER PyObject *, PyObject *args )
 
  485    PyObject * ret = 
nullptr;
 
  491        if (PyArg_ParseTuple (args, 
"s", &name))
 
  493            OUString 
typeName ( OUString::createFromAscii( name ) );
 
  494            TypeDescription typeDesc( typeName );
 
  499                    name, 
static_cast<css::uno::TypeClass
>(typeDesc.get()->eTypeClass), runtime );
 
  503                OString buf = OString::Concat(
"Type ") + 
name +  
" is unknown";
 
  504                PyErr_SetString( PyExc_RuntimeError, buf.getStr() );
 
  508    catch ( 
const RuntimeException & e )
 
  516    SAL_UNUSED_PARAMETER PyObject *, PyObject *args )
 
  518    PyObject *ret = 
nullptr;
 
  523        if (PyArg_ParseTuple (args, 
"s", &name))
 
  525            OUString 
typeName ( OUString::createFromAscii( name ) );
 
  527            css::uno::Reference< css::reflection::XConstantTypeDescription > td;
 
  532                throw RuntimeException( 
"pyuno.getConstantByName: " + typeName + 
"is not a constant" );
 
  538    catch( 
const NoSuchElementException & e )
 
  542        RuntimeException runExc( e.Message );
 
  545    catch(
const css::script::CannotConvertException & e)
 
  549    catch(
const css::lang::IllegalArgumentException & e)
 
  553    catch( 
const RuntimeException & e )
 
  560static PyObject *
checkType( SAL_UNUSED_PARAMETER PyObject *, PyObject *args )
 
  562    if( !PyTuple_Check( args ) || PyTuple_Size( args) != 1 )
 
  564        OString buf = 
"pyuno.checkType : expecting one uno.Type argument";
 
  565        PyErr_SetString( PyExc_RuntimeError, buf.getStr() );
 
  568    PyObject *obj = PyTuple_GetItem( args, 0 );
 
  574    catch(
const  RuntimeException & e)
 
  579    Py_INCREF( Py_None );
 
  583static PyObject *checkEnum( SAL_UNUSED_PARAMETER PyObject *, PyObject *args )
 
  585    if( !PyTuple_Check( args ) || PyTuple_Size( args) != 1 )
 
  587        OString buf = 
"pyuno.checkType : expecting one uno.Type argument";
 
  588        PyErr_SetString( PyExc_RuntimeError, buf.getStr() );
 
  591    PyObject *obj = PyTuple_GetItem( args, 0 );
 
  597    catch(
const RuntimeException & e)
 
  602    Py_INCREF( Py_None );
 
  606static PyObject *
getClass( SAL_UNUSED_PARAMETER PyObject *, PyObject *args )
 
  608    PyObject *obj = extractOneStringArg( args, 
"pyuno.getClass");
 
  616        Py_XINCREF( ret.
get() );
 
  619    catch(
const RuntimeException & e)
 
  626static PyObject *
isInterface( SAL_UNUSED_PARAMETER PyObject *, PyObject *args )
 
  629    if( PyTuple_Check( args ) && PyTuple_Size( args ) == 1 )
 
  631        PyObject *obj = PyTuple_GetItem( args, 0 );
 
  635    return PyLong_FromLong( 0 );
 
  639    SAL_UNUSED_PARAMETER PyObject *, SAL_UNUSED_PARAMETER PyObject * )
 
  642    rtl_createUuid( 
reinterpret_cast<sal_uInt8*
>(seq.getArray()) , 
nullptr , 
false );
 
  649    catch( 
const RuntimeException & e )
 
  657    SAL_UNUSED_PARAMETER PyObject *, PyObject * args )
 
  659    PyObject *obj = extractOneStringArg( args, 
"pyuno.systemPathToFileUrl" );
 
  665    osl::FileBase::RC e = osl::FileBase::getFileURLFromSystemPath( sysPath, url );
 
  667    if( e != osl::FileBase::E_None )
 
  669        OUString buf = 
"Couldn't convert " +
 
  671                " to a file url for reason (" +
 
  672                OUString::number( 
static_cast<sal_Int32
>(e) ) +
 
  675            Any( RuntimeException( buf )));
 
  682    SAL_UNUSED_PARAMETER PyObject *, PyObject * args )
 
  684    PyObject *obj = extractOneStringArg( args, 
"pyuno.fileUrlToSystemPath" );
 
  690    osl::FileBase::RC e = osl::FileBase::getSystemPathFromFileURL( url, sysPath );
 
  692    if( e != osl::FileBase::E_None )
 
  694        OUString buf = 
"Couldn't convert file url " +
 
  696                " to a system path for reason (" +
 
  697                OUString::number( 
static_cast<sal_Int32
>(e) ) +
 
  700            Any( RuntimeException( buf )));
 
  706static PyObject * 
absolutize( SAL_UNUSED_PARAMETER PyObject *, PyObject * args )
 
  708    if( !PyTuple_Check( args ) || PyTuple_Size( args ) != 2 )
 
  714    oslFileError e = osl_getAbsoluteFileURL( ouPath.pData, ouRel.pData, &(ret.pData) );
 
  715    if( e != osl_File_E_None )
 
  718                "Couldn't absolutize " +
 
  723                OUString::number(
static_cast<sal_Int32
>(e) ) +
 
  734static PyObject * 
invoke(SAL_UNUSED_PARAMETER PyObject *, PyObject *args)
 
  736    PyObject *ret = 
nullptr;
 
  737    if(PyTuple_Check(args) && PyTuple_Size(args) == 3)
 
  739        PyObject *
object = PyTuple_GetItem(args, 0);
 
  740        PyObject *item1 = PyTuple_GetItem(args, 1);
 
  741        if (PyUnicode_Check(item1))
 
  743            const char *
name = PyUnicode_AsUTF8(item1);
 
  744            PyObject *item2 = PyTuple_GetItem(args, 2);
 
  745            if(PyTuple_Check(item2))
 
  751                OString buf = OString::Concat(
"uno.invoke expects a tuple as 3rd argument, got ")
 
  752                    + PyUnicode_AsUTF8(PyObject_Str(item2));
 
  754                    PyExc_RuntimeError, buf.getStr());
 
  759            OString buf = OString::Concat(
"uno.invoke expected a string as 2nd argument, got ")
 
  760                + PyUnicode_AsUTF8(PyObject_Str(item1));
 
  762                PyExc_RuntimeError, buf.getStr());
 
  767        OString buf = 
"uno.invoke expects object, name, (arg1, arg2, ... )\n";
 
  768        PyErr_SetString(PyExc_RuntimeError, buf.getStr());
 
  774    SAL_UNUSED_PARAMETER PyObject *, SAL_UNUSED_PARAMETER PyObject * )
 
  783    catch( 
const css::uno::Exception & e )
 
  791    SAL_UNUSED_PARAMETER PyObject *, SAL_UNUSED_PARAMETER PyObject * args )
 
  796        if( PyTuple_Check( args ) && PyTuple_Size( args ) == 1 )
 
  804            if( (
a.hasValue() && (a >>= context)) || ! 
a.hasValue() )
 
  811                    OString::Concat(
"uno.setCurrentContext expects an XComponentContext implementation, got ")
 
  812                    + PyUnicode_AsUTF8(PyObject_Str(PyTuple_GetItem(args, 0)));
 
  814                    PyExc_RuntimeError, buf.getStr() );
 
  819            OString buf = 
"uno.setCurrentContext expects exactly one argument (the current Context)\n";
 
  821                PyExc_RuntimeError, buf.getStr() );
 
  824    catch( 
const css::uno::Exception & e )
 
  831static PyObject *sal_debug(
 
  832    SAL_UNUSED_PARAMETER PyObject *, SAL_UNUSED_PARAMETER PyObject * args )
 
  834    Py_INCREF( Py_None );
 
  835    if( !PyTuple_Check( args ) || PyTuple_Size( args) != 1 )
 
  847struct PyMethodDef PyUNOModule_methods [] =
 
  849    {
"private_initTestEnvironment", initTestEnvironment, METH_VARARGS, 
nullptr},
 
  850    {
"private_deinitTestEnvironment", deinitTestEnvironment, METH_VARARGS, 
nullptr},
 
  852    {
"_createUnoStructHelper", 
reinterpret_cast<PyCFunction
>(createUnoStructHelper), METH_VARARGS | METH_KEYWORDS, 
nullptr},
 
  855    {
"getClass", 
getClass, METH_VARARGS, 
nullptr},
 
  856    {
"checkEnum", checkEnum, METH_VARARGS, 
nullptr},
 
  857    {
"checkType", 
checkType, METH_VARARGS, 
nullptr},
 
  861    {
"absolutize", 
absolutize, METH_VARARGS | METH_KEYWORDS, 
nullptr},
 
  862    {
"isInterface", 
isInterface, METH_VARARGS, 
nullptr},
 
  863    {
"invoke", 
invoke, METH_VARARGS | METH_KEYWORDS, 
nullptr},
 
  866    {
"sal_debug", sal_debug, METH_VARARGS, 
nullptr},
 
  867    {
nullptr, 
nullptr, 0, 
nullptr}
 
  878#if PY_VERSION_HEX < 0x03090000 
  879    PyEval_InitThreads();
 
  881    static struct PyModuleDef moduledef =
 
  883        PyModuleDef_HEAD_INIT,
 
  893    return PyModule_Create(&moduledef);
 
Helper class for keeping references to python objects.
 
PyObject * get() const noexcept
 
PyObject * getAcquired() const
 
helper class for detaching the current thread from the python runtime to do some blocking,...
 
The pyuno::Runtime class keeps the internal state of the python UNO bridge for the currently in use p...
 
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
 
RuntimeImpl * getImpl() const
Returns the internal handle.
 
#define SAL_CONFIGFILE(name)
 
#define SAL_DEBUG(stream)
 
void fillStruct(const typelib_TypeDescription *pTypeDescr, sal_Int64 *gret, double *fret, void *pRegisterReturn)
 
CPPUHELPER_DLLPUBLIC css::uno::Reference< css::uno::XComponentContext > SAL_CALL defaultBootstrap_InitialComponentContext()
 
def systemPathToFileUrl(systemPath)
 
def fileUrlToSystemPath(url)
 
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
 
PyObject * PyUNO_Type_new(const char *typeName, css::uno::TypeClass t, const Runtime &r)
 
int PyUNOStruct_initType()
 
void raisePyExceptionWithAny(const css::uno::Any &anyExc)
 
css::uno::Type PyType2Type(PyObject *o)
 
bool isInterfaceClass(const Runtime &runtime, PyObject *obj)
 
OUString pyString2ustring(PyObject *str)
 
PyObject * PyUNO_invoke(PyObject *object, const char *name, PyObject *args)
 
PyRef ustring2PyUnicode(const OUString &source)
 
PyRef getClass(const OUString &name, const Runtime &runtime)
 
css::uno::Any PyEnum2Enum(PyObject *obj)
 
PyRef PyUNOStruct_new(const css::uno::Any &targetInterface, const css::uno::Reference< css::lang::XSingleServiceFactory > &ssf)
 
void checkType(rtl::Reference< TypeManager > const &manager, OUString const &name, std::set< OUString > &interfaceTypes, std::set< OUString > &serviceTypes, AttributeInfo &properties)
 
def absolutize(path, relativeUrl)
 
def invoke(object, methodname, argTuple)
 
def getComponentContext()
 
def getConstantByName(constant)
 
def getTypeByName(typeName)
 
def setCurrentContext(newContext)
 
PyObject * PyInit_pyuno()
function called by the python runtime to initialize the pyuno module.
 
css::uno::Reference< css::script::XInvocation2 > xInvocation
 
PyObject_HEAD PyUNOInternals * members
 
css::uno::Reference< css::reflection::XIdlReflection > xCoreReflection
 
css::uno::Reference< css::lang::XSingleServiceFactory > xInvocation
 
css::uno::Reference< css::container::XHierarchicalNameAccess > xTdMgr
 
css::uno::Reference< css::uno::XComponentContext > xContext
 
PyObject_HEAD struct RuntimeCargo * cargo