LibreOffice Module pyuno (master) 1
pyuno_module.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; eval:(c-set-style "bsd"); tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <config_folders.h>
21
22#include "pyuno_impl.hxx"
23
24#include <cassert>
25#include <string_view>
26#include <unordered_map>
27
28#include <osl/module.hxx>
29#include <osl/thread.h>
30#include <osl/file.hxx>
31#include <sal/log.hxx>
32
33#include <typelib/typedescription.hxx>
34
35#include <rtl/ustring.hxx>
36#include <rtl/strbuf.hxx>
37#include <rtl/ustrbuf.hxx>
38#include <rtl/uuid.h>
39#include <rtl/bootstrap.hxx>
40
41#include <uno/current_context.hxx>
43
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>
53
54using osl::Module;
55
56
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;
66
67using namespace pyuno;
68
69namespace {
70
74// LEM TODO: export member names as keyword arguments in initialiser?
75// Python supports very flexible variadic functions. By marking
76// variables with one asterisk (e.g. *var) the given variable is
77// defined to be a tuple of all the extra arguments. By marking
78// variables with two asterisks (e.g. **var) the given variable is a
79// dictionary of all extra keyword arguments; the keys are strings,
80// which are the names that were used to identify the arguments. If
81// they exist, these arguments must be the last one in the list.
82
83class fillStructState
84{
85 // Keyword arguments used
86 PyObject *used;
87 // Which structure members are initialised
88 std::unordered_map <OUString, bool> initialised;
89 // How many positional arguments are consumed
90 // This is always the so-many first ones
91 sal_Int32 nPosConsumed;
92
93public:
94 fillStructState()
95 : used (PyDict_New())
96 , nPosConsumed (0)
97 {
98 if ( ! used )
99 throw RuntimeException("pyuno._createUnoStructHelper failed to create new dictionary");
100 }
101 ~fillStructState()
102 {
103 Py_DECREF(used);
104 }
105 void setUsed(PyObject *key)
106 {
107 PyDict_SetItem(used, key, Py_True);
108 }
109 void setInitialised(const OUString& key, sal_Int32 pos = -1)
110 {
111 if (initialised[key])
112 {
113 OUStringBuffer buf( "pyuno._createUnoStructHelper: member '" + key + "'");
114 if ( pos >= 0 )
115 {
116 buf.append( " at position " + OUString::number(pos));
117 }
118 buf.append( " initialised multiple times.");
119 throw RuntimeException(buf.makeStringAndClear());
120 }
121 initialised[key] = true;
122 if ( pos >= 0 )
123 ++nPosConsumed;
124 }
125 bool isInitialised(const OUString& key)
126 {
127 return initialised[key];
128 }
129 PyObject *getUsed() const
130 {
131 return used;
132 }
133 sal_Int32 getCntConsumed() const
134 {
135 return nPosConsumed;
136 }
137};
138
140void fillStruct(
141 const Reference< XInvocation2 > &inv,
142 typelib_CompoundTypeDescription *pCompType,
143 PyObject *initializer,
144 PyObject *kwinitializer,
145 fillStructState &state,
146 const Runtime &runtime)
147{
148 if( pCompType->pBaseTypeDescription )
149 fillStruct( inv, pCompType->pBaseTypeDescription, initializer, kwinitializer, state, runtime );
150
151 const sal_Int32 nMembers = pCompType->nMembers;
152 {
153 for( int i = 0 ; i < nMembers ; i ++ )
154 {
155 const OUString OUMemberName (pCompType->ppMemberNames[i]);
156 PyObject *pyMemberName =
157 PyUnicode_FromString(OUStringToOString(OUMemberName,
158 RTL_TEXTENCODING_UTF8).getStr());
159 if ( PyObject *element = PyDict_GetItem(kwinitializer, pyMemberName ) )
160 {
161 state.setInitialised(OUMemberName);
162 state.setUsed(pyMemberName);
163 Any a = runtime.pyObject2Any( element, ACCEPT_UNO_ANY );
164 inv->setValue( OUMemberName, a );
165 }
166 }
167 }
168 {
169 const int remainingPosInitialisers = PyTuple_Size(initializer) - state.getCntConsumed();
170 for( int i = 0 ; i < remainingPosInitialisers && i < nMembers ; i ++ )
171 {
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 );
176 Any a = runtime.pyObject2Any( element, ACCEPT_UNO_ANY );
177 inv->setValue( rMemberName, a );
178 }
179 }
180 if ( PyTuple_Size( initializer ) <= 0 )
181 return;
182
183 // Allow partial initialisation when only keyword arguments are given
184 for ( int i = 0; i < nMembers ; ++i)
185 {
186 const OUString memberName (pCompType->ppMemberNames[i]);
187 if ( ! state.isInitialised( memberName ) )
188 {
189 OUString buf = "pyuno._createUnoStructHelper: member '" +
190 memberName +
191 "' of struct type '" +
192 OUString::unacquired(&pCompType->aBase.pTypeName) +
193 "' not given a value.";
194 throw RuntimeException(buf);
195 }
196 }
197}
198
199OUString getLibDir()
200{
201 static OUString sLibDir = []() {
202 OUString libDir;
203
204 // workarounds the $(ORIGIN) until it is available
205 if (Module::getUrlFromAddress(reinterpret_cast<oslGenericFunction>(getLibDir), libDir))
206 {
207 libDir = libDir.copy(0, libDir.lastIndexOf('/'));
208 OUString name("PYUNOLIBDIR");
209 rtl_bootstrap_set(name.pData, libDir.pData);
210 }
211 return libDir;
212 }();
213
214 return sLibDir;
215}
216
217void raisePySystemException( const char * exceptionType, std::u16string_view message )
218{
219 OString buf = OString::Concat("Error during bootstrapping uno (") +
220 exceptionType +
221 "):" +
222 OUStringToOString( message, osl_getThreadTextEncoding() );
223 PyErr_SetString( PyExc_SystemError, buf.getStr() );
224}
225
226extern "C" {
227
228static PyObject* getComponentContext(
229 SAL_UNUSED_PARAMETER PyObject*, SAL_UNUSED_PARAMETER PyObject*)
230{
231 PyRef ret;
232 try
233 {
235
236 // getLibDir() must be called in order to set bootstrap variables correctly !
237 OUString path( getLibDir());
238 if( Runtime::isInitialized() )
239 {
240 Runtime runtime;
241 ctx = runtime.getImpl()->cargo->xContext;
242 }
243 else
244 {
245 if( path.isEmpty() )
246 {
247 PyErr_SetString(
248 PyExc_RuntimeError, "osl_getUrlFromAddress fails, that's why I cannot find ini "
249 "file for bootstrapping python uno bridge\n" );
250 return nullptr;
251 }
252
253 OUString iniFile = path +
254#ifdef MACOSX
255 "/../" LIBO_ETC_FOLDER
256#endif
257 "/" SAL_CONFIGFILE( "pyuno" );
258 osl::DirectoryItem item;
259 if( osl::DirectoryItem::get( iniFile, item ) == osl::FileBase::E_None )
260 {
261 // in case pyuno.ini exists, use this file for bootstrapping
262 PyThreadDetach antiguard;
264 }
265 else
266 {
267 // defaulting to the standard bootstrapping
268 PyThreadDetach antiguard;
270 }
271
272 }
273
274 if( ! Runtime::isInitialized() )
275 {
276 Runtime::initialize( ctx );
277 }
278 Runtime runtime;
279 ret = runtime.any2PyObject( Any( ctx ) );
280 }
281 catch (const css::registry::InvalidRegistryException &e)
282 {
283 // can't use raisePyExceptionWithAny() here, because the function
284 // does any conversions, which will not work with a
285 // wrongly bootstrapped pyuno!
286 raisePySystemException( "InvalidRegistryException", e.Message );
287 }
288 catch(const css::lang::IllegalArgumentException & e)
289 {
290 raisePySystemException( "IllegalArgumentException", e.Message );
291 }
292 catch(const css::script::CannotConvertException & e)
293 {
294 raisePySystemException( "CannotConvertException", e.Message );
295 }
296 catch (const css::uno::RuntimeException & e)
297 {
298 raisePySystemException( "RuntimeException", e.Message );
299 }
300 catch (const css::uno::Exception & e)
301 {
302 raisePySystemException( "uno::Exception", e.Message );
303 }
304 return ret.getAcquired();
305}
306
307// While pyuno.private_initTestEnvironment is called from individual Python tests (e.g., from
308// UnoInProcess in unotest/source/python/org/libreoffice/unotest.py, which makes sure to call it
309// only once), pyuno.private_deinitTestEnvironment is called centrally from
310// unotest/source/python/org/libreoffice/unittest.py at the end of every PythonTest (to DeInitVCL
311// exactly once near the end of the process, if InitVCL has ever been called via
312// pyuno.private_initTestEnvironment):
313
314osl::Module * testModule = nullptr;
315
316static PyObject* initTestEnvironment(
317 SAL_UNUSED_PARAMETER PyObject*, SAL_UNUSED_PARAMETER PyObject*)
318{
319 // this tries to bootstrap enough of the soffice from python to run
320 // unit tests, which is only possible indirectly because pyuno is URE
321 // so load "test" library and invoke a function there to do the work
322 assert(testModule == nullptr);
323 try
324 {
325 PyObject *const ctx(getComponentContext(nullptr, nullptr));
326 if (!ctx) { abort(); }
327 Runtime const runtime;
328 Any const a(runtime.pyObject2Any(ctx));
330 a >>= xContext;
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(); }
338#ifdef _WIN32
339 OString const libname = OString(testlib, strlen(testlib))
340 .replaceAll(OString('/'), OString('\\'));
341#else
342 OString const libname(testlib, strlen(testlib));
343#endif
344
345 osl::Module &mod = runtime.getImpl()->cargo->testModule;
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());
353 testModule = &mod;
354 }
355 catch (const css::uno::Exception &)
356 {
357 abort();
358 }
359 return Py_None;
360}
361
362static PyObject* deinitTestEnvironment(
363 SAL_UNUSED_PARAMETER PyObject*, SAL_UNUSED_PARAMETER PyObject*)
364{
365 if (testModule != nullptr)
366 {
367 try
368 {
369 oslGenericFunction const pFunc(
370 testModule->getFunctionSymbol("test_deinit"));
371 if (!pFunc) { abort(); }
372 reinterpret_cast<void (SAL_CALL *)()>(pFunc)();
373 }
374 catch (const css::uno::Exception &)
375 {
376 abort();
377 }
378 }
379 return Py_None;
380}
381
382PyObject * extractOneStringArg( PyObject *args, char const *funcName )
383{
384 if( !PyTuple_Check( args ) || PyTuple_Size( args) != 1 )
385 {
386 OString buf = funcName + OString::Concat(": expecting one string argument");
387 PyErr_SetString( PyExc_RuntimeError, buf.getStr() );
388 return nullptr;
389 }
390 PyObject *obj = PyTuple_GetItem( args, 0 );
391 if (!PyUnicode_Check(obj))
392 {
393 OString buf = funcName + OString::Concat(": expecting one string argument");
394 PyErr_SetString( PyExc_TypeError, buf.getStr());
395 return nullptr;
396 }
397 return obj;
398}
399
400static PyObject *createUnoStructHelper(
401 SAL_UNUSED_PARAMETER PyObject *, PyObject* args, PyObject* keywordArgs)
402{
403 Any IdlStruct;
404 PyRef ret;
405 try
406 {
407 Runtime runtime;
408 if( PyTuple_Size( args ) == 2 )
409 {
410 PyObject *structName = PyTuple_GetItem(args, 0);
411 PyObject *initializer = PyTuple_GetItem(args, 1);
412
413 if (PyUnicode_Check(structName))
414 {
415 if( PyTuple_Check( initializer ) && PyDict_Check ( keywordArgs ) )
416 {
417 OUString typeName( OUString::createFromAscii(PyUnicode_AsUTF8(structName)));
418 RuntimeCargo *c = runtime.getImpl()->cargo;
419 Reference<XIdlClass> idl_class = c->xCoreReflection->forName (typeName);
420 if (idl_class.is ())
421 {
422 idl_class->createObject (IdlStruct);
423 PyRef returnCandidate( PyUNOStruct_new( IdlStruct, c->xInvocation ) );
424 PyUNO *me = reinterpret_cast<PyUNO*>( returnCandidate.get() );
425 TypeDescription desc( typeName );
426 OSL_ASSERT( desc.is() ); // could already instantiate an XInvocation2 !
427
428 typelib_CompoundTypeDescription *pCompType =
429 reinterpret_cast<typelib_CompoundTypeDescription *>(desc.get());
430 fillStructState state;
431 if ( PyTuple_Size( initializer ) > 0 || PyDict_Size( keywordArgs ) > 0 )
432 fillStruct( me->members->xInvocation, pCompType, initializer, keywordArgs, state, runtime );
433 if( state.getCntConsumed() != PyTuple_Size(initializer) )
434 {
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) ) );
439 }
440 ret = PyRef( PyTuple_Pack(2, returnCandidate.get(), state.getUsed()), SAL_NO_ACQUIRE);
441 }
442 else
443 {
444 OString buf = OString::Concat("UNO struct ")
445 + PyUnicode_AsUTF8(structName)
446 + " is unknown";
447 PyErr_SetString (PyExc_RuntimeError, buf.getStr());
448 }
449 }
450 else
451 {
452 PyErr_SetString(
453 PyExc_RuntimeError,
454 "pyuno._createUnoStructHelper: 2nd argument (initializer sequence) is no tuple" );
455 }
456 }
457 else
458 {
459 PyErr_SetString (PyExc_AttributeError, "createUnoStruct: first argument wasn't a string");
460 }
461 }
462 else
463 {
464 PyErr_SetString (PyExc_AttributeError, "pyuno._createUnoStructHelper: expects exactly two non-keyword arguments:\n\tStructure Name\n\tinitialiser tuple; may be the empty tuple");
465 }
466 }
467 catch( const css::uno::RuntimeException & e )
468 {
470 }
471 catch( const css::script::CannotConvertException & e )
472 {
474 }
475 catch( const css::uno::Exception & e )
476 {
478 }
479 return ret.getAcquired();
480}
481
482static PyObject *getTypeByName(
483 SAL_UNUSED_PARAMETER PyObject *, PyObject *args )
484{
485 PyObject * ret = nullptr;
486
487 try
488 {
489 char *name;
490
491 if (PyArg_ParseTuple (args, "s", &name))
492 {
493 OUString typeName ( OUString::createFromAscii( name ) );
494 TypeDescription typeDesc( typeName );
495 if( typeDesc.is() )
496 {
497 Runtime runtime;
498 ret = PyUNO_Type_new(
499 name, static_cast<css::uno::TypeClass>(typeDesc.get()->eTypeClass), runtime );
500 }
501 else
502 {
503 OString buf = OString::Concat("Type ") + name + " is unknown";
504 PyErr_SetString( PyExc_RuntimeError, buf.getStr() );
505 }
506 }
507 }
508 catch ( const RuntimeException & e )
509 {
511 }
512 return ret;
513}
514
515static PyObject *getConstantByName(
516 SAL_UNUSED_PARAMETER PyObject *, PyObject *args )
517{
518 PyObject *ret = nullptr;
519 try
520 {
521 char *name;
522
523 if (PyArg_ParseTuple (args, "s", &name))
524 {
525 OUString typeName ( OUString::createFromAscii( name ) );
526 Runtime runtime;
527 css::uno::Reference< css::reflection::XConstantTypeDescription > td;
528 if (!(runtime.getImpl()->cargo->xTdMgr->getByHierarchicalName(
529 typeName)
530 >>= td))
531 {
532 throw RuntimeException( "pyuno.getConstantByName: " + typeName + "is not a constant" );
533 }
534 PyRef constant = runtime.any2PyObject( td->getConstantValue() );
535 ret = constant.getAcquired();
536 }
537 }
538 catch( const NoSuchElementException & e )
539 {
540 // to the python programmer, this is a runtime exception,
541 // do not support tweakings with the type system
542 RuntimeException runExc( e.Message );
543 raisePyExceptionWithAny( Any( runExc ) );
544 }
545 catch(const css::script::CannotConvertException & e)
546 {
548 }
549 catch(const css::lang::IllegalArgumentException & e)
550 {
552 }
553 catch( const RuntimeException & e )
554 {
556 }
557 return ret;
558}
559
560static PyObject *checkType( SAL_UNUSED_PARAMETER PyObject *, PyObject *args )
561{
562 if( !PyTuple_Check( args ) || PyTuple_Size( args) != 1 )
563 {
564 OString buf = "pyuno.checkType : expecting one uno.Type argument";
565 PyErr_SetString( PyExc_RuntimeError, buf.getStr() );
566 return nullptr;
567 }
568 PyObject *obj = PyTuple_GetItem( args, 0 );
569
570 try
571 {
572 PyType2Type( obj );
573 }
574 catch(const RuntimeException & e)
575 {
577 return nullptr;
578 }
579 Py_INCREF( Py_None );
580 return Py_None;
581}
582
583static PyObject *checkEnum( SAL_UNUSED_PARAMETER PyObject *, PyObject *args )
584{
585 if( !PyTuple_Check( args ) || PyTuple_Size( args) != 1 )
586 {
587 OString buf = "pyuno.checkType : expecting one uno.Type argument";
588 PyErr_SetString( PyExc_RuntimeError, buf.getStr() );
589 return nullptr;
590 }
591 PyObject *obj = PyTuple_GetItem( args, 0 );
592
593 try
594 {
595 PyEnum2Enum( obj );
596 }
597 catch(const RuntimeException & e)
598 {
600 return nullptr;
601 }
602 Py_INCREF( Py_None );
603 return Py_None;
604}
605
606static PyObject *getClass( SAL_UNUSED_PARAMETER PyObject *, PyObject *args )
607{
608 PyObject *obj = extractOneStringArg( args, "pyuno.getClass");
609 if( ! obj )
610 return nullptr;
611
612 try
613 {
614 Runtime runtime;
615 PyRef ret = getClass(pyString2ustring(obj), runtime);
616 Py_XINCREF( ret.get() );
617 return ret.get();
618 }
619 catch(const RuntimeException & e)
620 {
622 }
623 return nullptr;
624}
625
626static PyObject *isInterface( SAL_UNUSED_PARAMETER PyObject *, PyObject *args )
627{
628
629 if( PyTuple_Check( args ) && PyTuple_Size( args ) == 1 )
630 {
631 PyObject *obj = PyTuple_GetItem( args, 0 );
632 Runtime r;
633 return PyLong_FromLong( isInterfaceClass( r, obj ) );
634 }
635 return PyLong_FromLong( 0 );
636}
637
638static PyObject * generateUuid(
639 SAL_UNUSED_PARAMETER PyObject *, SAL_UNUSED_PARAMETER PyObject * )
640{
641 Sequence< sal_Int8 > seq( 16 );
642 rtl_createUuid( reinterpret_cast<sal_uInt8*>(seq.getArray()) , nullptr , false );
643 PyRef ret;
644 try
645 {
646 Runtime runtime;
647 ret = runtime.any2PyObject( Any( seq ) );
648 }
649 catch( const RuntimeException & e )
650 {
652 }
653 return ret.getAcquired();
654}
655
656static PyObject *systemPathToFileUrl(
657 SAL_UNUSED_PARAMETER PyObject *, PyObject * args )
658{
659 PyObject *obj = extractOneStringArg( args, "pyuno.systemPathToFileUrl" );
660 if( ! obj )
661 return nullptr;
662
663 OUString sysPath = pyString2ustring( obj );
664 OUString url;
665 osl::FileBase::RC e = osl::FileBase::getFileURLFromSystemPath( sysPath, url );
666
667 if( e != osl::FileBase::E_None )
668 {
669 OUString buf = "Couldn't convert " +
670 sysPath +
671 " to a file url for reason (" +
672 OUString::number( static_cast<sal_Int32>(e) ) +
673 ")";
675 Any( RuntimeException( buf )));
676 return nullptr;
677 }
678 return ustring2PyUnicode( url ).getAcquired();
679}
680
681static PyObject * fileUrlToSystemPath(
682 SAL_UNUSED_PARAMETER PyObject *, PyObject * args )
683{
684 PyObject *obj = extractOneStringArg( args, "pyuno.fileUrlToSystemPath" );
685 if( ! obj )
686 return nullptr;
687
688 OUString url = pyString2ustring( obj );
689 OUString sysPath;
690 osl::FileBase::RC e = osl::FileBase::getSystemPathFromFileURL( url, sysPath );
691
692 if( e != osl::FileBase::E_None )
693 {
694 OUString buf = "Couldn't convert file url " +
695 sysPath +
696 " to a system path for reason (" +
697 OUString::number( static_cast<sal_Int32>(e) ) +
698 ")";
700 Any( RuntimeException( buf )));
701 return nullptr;
702 }
703 return ustring2PyUnicode( sysPath ).getAcquired();
704}
705
706static PyObject * absolutize( SAL_UNUSED_PARAMETER PyObject *, PyObject * args )
707{
708 if( !PyTuple_Check( args ) || PyTuple_Size( args ) != 2 )
709 return nullptr;
710
711 OUString ouPath = pyString2ustring( PyTuple_GetItem( args , 0 ) );
712 OUString ouRel = pyString2ustring( PyTuple_GetItem( args, 1 ) );
713 OUString ret;
714 oslFileError e = osl_getAbsoluteFileURL( ouPath.pData, ouRel.pData, &(ret.pData) );
715 if( e != osl_File_E_None )
716 {
717 OUString buf =
718 "Couldn't absolutize " +
719 ouRel +
720 " using root " +
721 ouPath +
722 " for reason (" +
723 OUString::number(static_cast<sal_Int32>(e) ) +
724 ")";
725
726 PyErr_SetString(
727 PyExc_OSError,
728 OUStringToOString(buf,osl_getThreadTextEncoding()).getStr());
729 return nullptr;
730 }
731 return ustring2PyUnicode( ret ).getAcquired();
732}
733
734static PyObject * invoke(SAL_UNUSED_PARAMETER PyObject *, PyObject *args)
735{
736 PyObject *ret = nullptr;
737 if(PyTuple_Check(args) && PyTuple_Size(args) == 3)
738 {
739 PyObject *object = PyTuple_GetItem(args, 0);
740 PyObject *item1 = PyTuple_GetItem(args, 1);
741 if (PyUnicode_Check(item1))
742 {
743 const char *name = PyUnicode_AsUTF8(item1);
744 PyObject *item2 = PyTuple_GetItem(args, 2);
745 if(PyTuple_Check(item2))
746 {
747 ret = PyUNO_invoke(object, name, item2);
748 }
749 else
750 {
751 OString buf = OString::Concat("uno.invoke expects a tuple as 3rd argument, got ")
752 + PyUnicode_AsUTF8(PyObject_Str(item2));
753 PyErr_SetString(
754 PyExc_RuntimeError, buf.getStr());
755 }
756 }
757 else
758 {
759 OString buf = OString::Concat("uno.invoke expected a string as 2nd argument, got ")
760 + PyUnicode_AsUTF8(PyObject_Str(item1));
761 PyErr_SetString(
762 PyExc_RuntimeError, buf.getStr());
763 }
764 }
765 else
766 {
767 OString buf = "uno.invoke expects object, name, (arg1, arg2, ... )\n";
768 PyErr_SetString(PyExc_RuntimeError, buf.getStr());
769 }
770 return ret;
771}
772
773static PyObject *getCurrentContext(
774 SAL_UNUSED_PARAMETER PyObject *, SAL_UNUSED_PARAMETER PyObject * )
775{
776 PyRef ret;
777 try
778 {
779 Runtime runtime;
780 ret = runtime.any2PyObject(
782 }
783 catch( const css::uno::Exception & e )
784 {
786 }
787 return ret.getAcquired();
788}
789
790static PyObject *setCurrentContext(
791 SAL_UNUSED_PARAMETER PyObject *, SAL_UNUSED_PARAMETER PyObject * args )
792{
793 PyRef ret;
794 try
795 {
796 if( PyTuple_Check( args ) && PyTuple_Size( args ) == 1 )
797 {
798
799 Runtime runtime;
800 Any a = runtime.pyObject2Any( PyTuple_GetItem( args, 0 ) );
801
803
804 if( (a.hasValue() && (a >>= context)) || ! a.hasValue() )
805 {
806 ret = css::uno::setCurrentContext( context ) ? Py_True : Py_False;
807 }
808 else
809 {
810 OString buf =
811 OString::Concat("uno.setCurrentContext expects an XComponentContext implementation, got ")
812 + PyUnicode_AsUTF8(PyObject_Str(PyTuple_GetItem(args, 0)));
813 PyErr_SetString(
814 PyExc_RuntimeError, buf.getStr() );
815 }
816 }
817 else
818 {
819 OString buf = "uno.setCurrentContext expects exactly one argument (the current Context)\n";
820 PyErr_SetString(
821 PyExc_RuntimeError, buf.getStr() );
822 }
823 }
824 catch( const css::uno::Exception & e )
825 {
827 }
828 return ret.getAcquired();
829}
830
831static PyObject *sal_debug(
832 SAL_UNUSED_PARAMETER PyObject *, SAL_UNUSED_PARAMETER PyObject * args )
833{
834 Py_INCREF( Py_None );
835 if( !PyTuple_Check( args ) || PyTuple_Size( args) != 1 )
836 return Py_None;
837
838 OUString line = pyString2ustring( PyTuple_GetItem( args, 0 ) );
839
840 SAL_DEBUG(line);
841
842 return Py_None;
843}
844
845}
846
847struct PyMethodDef PyUNOModule_methods [] =
848{
849 {"private_initTestEnvironment", initTestEnvironment, METH_VARARGS, nullptr},
850 {"private_deinitTestEnvironment", deinitTestEnvironment, METH_VARARGS, nullptr},
851 {"getComponentContext", getComponentContext, METH_VARARGS, nullptr},
852 {"_createUnoStructHelper", reinterpret_cast<PyCFunction>(createUnoStructHelper), METH_VARARGS | METH_KEYWORDS, nullptr},
853 {"getTypeByName", getTypeByName, METH_VARARGS, nullptr},
854 {"getConstantByName", getConstantByName, METH_VARARGS, nullptr},
855 {"getClass", getClass, METH_VARARGS, nullptr},
856 {"checkEnum", checkEnum, METH_VARARGS, nullptr},
857 {"checkType", checkType, METH_VARARGS, nullptr},
858 {"generateUuid", generateUuid, METH_VARARGS, nullptr},
859 {"systemPathToFileUrl", systemPathToFileUrl, METH_VARARGS, nullptr},
860 {"fileUrlToSystemPath", fileUrlToSystemPath, 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},
864 {"setCurrentContext", setCurrentContext, METH_VARARGS, nullptr},
865 {"getCurrentContext", getCurrentContext, METH_VARARGS, nullptr},
866 {"sal_debug", sal_debug, METH_VARARGS, nullptr},
867 {nullptr, nullptr, 0, nullptr}
868};
869
870}
871
872extern "C"
873PyObject* PyInit_pyuno()
874{
877 // noop when called already, otherwise needed to allow multiple threads
878#if PY_VERSION_HEX < 0x03090000
879 PyEval_InitThreads();
880#endif
881 static struct PyModuleDef moduledef =
882 {
883 PyModuleDef_HEAD_INIT,
884 "pyuno", // module name
885 nullptr, // module documentation
886 -1, // module keeps state in global variables,
887 PyUNOModule_methods, // modules methods
888 nullptr, // m_reload (must be 0)
889 nullptr, // m_traverse
890 nullptr, // m_clear
891 nullptr, // m_free
892 };
893 return PyModule_Create(&moduledef);
894}
895
896/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Helper class for keeping references to python objects.
Definition: pyuno.hxx:80
PyObject * get() const noexcept
Definition: pyuno.hxx:99
PyObject * getAcquired() const
Definition: pyuno.hxx:101
helper class for detaching the current thread from the python runtime to do some blocking,...
Definition: pyuno.hxx:300
The pyuno::Runtime class keeps the internal state of the python UNO bridge for the currently in use p...
Definition: pyuno.hxx:164
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.
Definition: pyuno.hxx:242
#define SAL_CONFIGFILE(name)
const char * name
uno_Any a
#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()
int i
line
ctx
def systemPathToFileUrl(systemPath)
def fileUrlToSystemPath(url)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
Definition: pyuno.cxx:72
PyObject * PyUNO_Type_new(const char *typeName, css::uno::TypeClass t, const Runtime &r)
@ ACCEPT_UNO_ANY
Definition: pyuno.hxx:153
int PyUNOStruct_initType()
void raisePyExceptionWithAny(const css::uno::Any &anyExc)
css::uno::Type PyType2Type(PyObject *o)
Definition: pyuno_type.cxx:195
bool isInterfaceClass(const Runtime &runtime, PyObject *obj)
int PyUNO_initType()
Definition: pyuno.cxx:1674
OUString pyString2ustring(PyObject *str)
Definition: pyuno_util.cxx:57
PyObject * PyUNO_invoke(PyObject *object, const char *name, PyObject *args)
Definition: pyuno.cxx:379
PyRef ustring2PyUnicode(const OUString &source)
Definition: pyuno_util.cxx:34
PyRef getClass(const OUString &name, const Runtime &runtime)
css::uno::Any PyEnum2Enum(PyObject *obj)
Definition: pyuno_type.cxx:145
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 generateUuid()
Definition: uno.py:112
def absolutize(path, relativeUrl)
Definition: uno.py:136
def invoke(object, methodname, argTuple)
Definition: uno.py:330
def getCurrentContext()
Definition: uno.py:38
def getComponentContext()
Definition: uno.py:32
def isInterface(obj)
Definition: uno.py:106
def getConstantByName(constant)
Definition: uno.py:61
def getTypeByName(typeName)
Definition: uno.py:67
def setCurrentContext(newContext)
Definition: uno.py:48
OUString typeName
PyObject * PyInit_pyuno()
function called by the python runtime to initialize the pyuno module.
css::uno::Reference< css::script::XInvocation2 > xInvocation
Definition: pyuno_impl.hxx:131
PyObject_HEAD PyUNOInternals * members
Definition: pyuno_impl.hxx:138
osl::Module testModule
Definition: pyuno_impl.hxx:224
css::uno::Reference< css::reflection::XIdlReflection > xCoreReflection
Definition: pyuno_impl.hxx:219
css::uno::Reference< css::lang::XSingleServiceFactory > xInvocation
Definition: pyuno_impl.hxx:216
css::uno::Reference< css::container::XHierarchicalNameAccess > xTdMgr
Definition: pyuno_impl.hxx:220
css::uno::Reference< css::uno::XComponentContext > xContext
Definition: pyuno_impl.hxx:218
PyObject_HEAD struct RuntimeCargo * cargo
Definition: pyuno_impl.hxx:238
unsigned char sal_uInt8