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