Example: Python Bridge PyUNO

From Apache OpenOffice Wiki
Jump to: navigation, search

This section provides an example of how the Python UNO bridge PyUNO bootstraps a service manager and how it makes use of the Invocation service to realize method invocation. While some parts are implementation or Python specific, the example provides a general understanding of language bindings.

The Python bridge PyUNO uses the cppu helper library to bootstrap a local service manager that is asked for a UnoUrlResolver service in Python.

In UNO.py, Python calls PyUNO.bootstrap() and receives a local component context. Note the parameter setup in that, it points to an ini file that configures the bootstrapped service manager with a type library. The file setup.ini corresponds to the uno.ini file that is used with the global service manager of the office.

  import PyUNO
  import os
  setup_ini = 'file:///%s/setup.ini' % os.getenv ('PWD') 
  class UNO:
      def __init__ ( self, connection='socket,host=localhost,port=2083;urp', setup=setup_ini ):
                """ do the bootstrap 
                    connection can be one or more of the following:
                    host = localhost | <hostname> | <ip-addr>,
                    port = <port>,
                    service = soffice,
                    user = <username>,
                    password = <password>
                self.XComponentContext = PyUNO.bootstrap ( setup )
                self.XUnoUrlResolver, o = \
                        self.XComponentContext.ServiceManager.createInstanceWithContext (
                                'com.sun.star.bridge.UnoUrlResolver', self.XComponentContext )
                self.XNamingService, o = self.XUnoUrlResolver.resolve (
                        'uno:%s;StarOffice.NamingService' % connection )
                self.XMultiServiceFactory, o = self.XNamingService.getRegisteredObject (
                self.XComponentLoader, o = \
                        self.XMultiServiceFactory.createInstance ( 'com.sun.star.frame.Desktop' )

Python uses function tables to map Python to C functions. PyUNO_module.cc defines a table with the mappings for the PyUNO object. As shown in the following example, PyUNO.bootstrap() is mapped to the C function newBootstrapPyUNO():

  static struct PyMethodDef PyUNOModule_methods [] =
    {"bootstrapPyUNO", bootstrapPyUNO, 1},
    {"bootstrap ", newBootstrapPyUNO , 1}, 
    {"createIdlStruct", createIdlStruct, 1},
    {"true", createTrueBool, 1},
    {"false", createFalseBool, 1},
    {NULL, NULL}

The function newBootstrapPyUNO() calls Util::bootstrap() in PyUNO_Util.cc and passes the location of the setup.ini file.

  static PyObject* newBootstrapPyUNO (PyObject* self, PyObject* args)
    char* ini_file_location;
    Reference<XComponentContext> tmp_cc;
    Any a;
    if (!PyArg_ParseTuple (args, "s", &ini_file_location))
      return NULL;
    tmp_cc = Util::bootstrap (ini_file_location);

Util::bootstrap() uses defaultBootstrap_InitialComponentContext(iniFile) from cppuhelper/bootstrap.hxx to create a local component context and its parameter iniFile points to the setup.ini file that configures the local service manager to use service.rdb and types.rdb (until 1.1.0 applicat.rdb). This local component context instantiates services, such as the UnoUrlResolver.

  Reference<XComponentContext> bootstrap (char* ini_file_location)
    Reference<XComponentContext> my_component_context;
        my_component_context = defaultBootstrap_InitialComponentContext (
                 OUString::createFromAscii (ini_file_location ));
    catch (com::sun::star::uno::Exception e)
        printf (OUStringToOString (e.Message, osl_getThreadTextEncoding ()).getStr ());
    return my_component_context;

Now newBootstrapPyUNO() continues to set up a UNO proxy. It creates local instances of com.sun.star.script.Invocation and com.sun.star.script.Converter, and calls PyUNO_new(), passing the local ComponentContext, a reference to the XSingleServiceFactory interface of com.sun.star.script.Invocation and a reference to the XTypeConverter interface of com.sun.star.script.Converter.

  static PyObject* newBootstrapPyUNO (PyObject* self, PyObject* args)
    char* ini_file_location;
    Reference<XComponentContext> tmp_cc;
    Any a;
    if (!PyArg_ParseTuple (args, "s", &ini_file_location))
      return NULL;
    tmp_cc = Util::bootstrap (ini_file_location) ;
    Reference<XMultiServiceFactory> tmp_msf (tmp_cc->getServiceManager (), UNO_QUERY);
    if (!tmp_msf.is ())
        PyErr_SetString (PyExc_RuntimeError, "Couldn't bootstrap from inifile");
        return NULL;
    Reference<XSingleServiceFactory> tmp_ssf (tmp_msf->createInstance (
        OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.script.Invocation "))), UNO_QUERY);
    Reference<XTypeConverter> tmp_tc (tmp_msf->createInstance (
        OUString (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.script.Converter "))), UNO_QUERY);
    if (!tmp_tc.is ())
        PyErr_SetString (PyExc_RuntimeError, "Couldn't create XTypeConverter");
        return NULL;
    if (!tmp_ssf.is ())
        PyErr_SetString (PyExc_RuntimeError, "Couldn't create XInvocation");
        return NULL;
    a <<= tmp_cc;
    return PyUNO_new (a, tmp_ssf, tmp_tc) ;

PyUNO_new() in PyUNO.cc is the function responsible for building all Python proxies. The call to PyUNO_new() here in newBootstrapPyUno() builds the first local PyUNO proxy for the ComponentContext object a which has been returned by Util::bootstrap().

For this purpose, PyUNO_new() uses the Invocation service to retrieve an XInvocation2 interface to the ComponentContext service passed in the parameter a:

  // PyUNO_new
  // creates Python object proxies for the given target UNO interfaces
  // targetInterface given UNO interface
  // ssf                     XSingleServiceFactory interface of com.sun.star.script.Invocation service
  // tc                      XTypeConverter interface of com.sun.star.script.Converter service
  PyObject* PyUNO_new (Any targetInterface, 
                    Reference<XSingleServiceFactory> ssf, 
                    Reference<XTypeConverter> tc)
    Sequence<Any> arguments (1);
    Reference<XInterface> tmp_interface;
    // put the target object into a sequence of Any for the call to 
    // ssf->createInstanceWithArguments()
    // ssf is the XSingleServiceFactory interface of the com.sun.star.script.Invocation service
    arguments[0] <<= targetInterface;
    // obtain com.sun.star.script.XInvocation2 for target object from Invocation
    // let Invocation create an XInvocation object for the Any in arguments
    tmp_interface = ssf->createInstanceWithArguments (arguments);
    // query XInvocation2 interface
    Reference<XInvocation2 > tmp_invocation (tmp_interface, UNO_QUERY);

The Python proxy invokes methods, and creates and converts UNO types. This Python specific and involves the implementation of several functions according to the Python API.

Finally __init__() in UNO.py in the above example uses the PyUNO object to obtain a local UnoUrlResolver that retrieves the initial object from the office.

Content on this page is licensed under the Public Documentation License (PDL).
Personal tools
In other languages