Introduction

This document is intended to be a guide for the SWIG for EDS bindings user. As so, it will include a description of the generic SWIG bindings and their functionality. When examples are due, we will be using Ruby as our coding language, although we will not use any of the ruby specific extensions. Such extensions (as other language specific extensions) can be found documented here.

Overall design

The overall design of the bindings closely mimic that of the e-d-s C library with some variations where those are fit. As a rule of thumb, one can consider that an e-d-s class corresponds to a binding class. There are however exceptions to this rule. As a second rule of thumb the following type of objects are translated to language specific types:

  • GList, GSList, etc.
  • Date and Time structures (ECalDateTime, icaltime. etc).
  • Primitive types (gint, gstring, gboolean, etc).
  • Any non Glib object will not be mapped.

Such conversions are done, and hopefully documented, in the language specific SWIG file (ruby.i for the ruby set of bindings)

Object mapping

Since e-d-s API is clearly object orientated, the bindings try hard to map getter/setter functions to properties. for example a call to e_source_peek_name(src) is mapped as an access to src.name property. More complex access like obtaining a GSList property work as expected and are translated to language specific classes (for example, in Ruby, an object of class GSList will get translated to an object of class Array). Some working examples, again in Ruby, follow:

 irb> require 'evolution'
 irb> src = Evolution::ESource.new("name","uri://",relative)  #creation of an ESource object
 irb> src.name = "new_name" 
 "new_name"  #setting it's name returns the new value
 irb> puts src.name # print the name to ensure it is correct...
 "new_name"     
 
 irb> #get a Ruby Array containing the EsourceGroups present in the computer
 irb> groups = Evolution.get_esource_groups # groups is now an ordinary Ruby array containing ESourceGroup objects
 irb> groups.each { |group| puts group.name } # list the name of EsourceGroups

Some equivalences between e-d-s objects and SWIG objects are given in the following table:

 e-d-s                          SWIG                     Ruby
 ================================================================================
 GSList                        language specific         Array
 GList                         language specific         Array
 ECalComponentDateTime         language specific         Time
 icaltimetype                  language specific         Time
 ECalComponentText             language specific         Array with 2 Strings or a String
 ESourceGroup                  ESourceGroup              Evolution::ESourceGroup
 ESource                       ESource                   Evolution::ESource
 ECal                          ECal                      Evolution::ECal 
 ECalComponent                 ECalComponent             Evolution::ECalComponent

Memory management

Memory management is too broad a subject to cover in such little space. However it's important for the users (and programmers) of the bindings to understand the goals SWIGforEDS tries to achieve and the mechanisms that it uses. This will be language specific, but will have consequences that apply to all language bindings the same.

In first place, we must explain the object mappings that SWIGforEDS uses. As can be seen in the diagram below, there are 3 different object layers which correspond to the two layers that are present in e-d-s and the SWIG objects.

                 1           *               1            1
 Logical object <-------------> Glib object <--------------> SWIG object

The logical object layer represents the logical objects in the model, for instance a calendar event. The Glib object is the glib representation the logical object, for instance, ECalComponent. The SWIG object is that language specific object, for example a Python or Ruby object, that interfaces the Glib object.

As noted in the diagram, Glib objects and SWIG objects are mapped 1 to 1. This is important, specially for binding programmers. because it means that garbage collection issues must be solved as there can be a mismatch between the reference counted GC scheme in GLib and the language specific GC mechanism (mark & sweep in ruby for instance). Also, due to the way objects are mapped in the ruby bindings, only Glib objects can be mapped.

While this should not matter for the ordinary binding user, the fact that 2 differnt GLib objects can refer to the same logical object still remains important. This mean's that ordinary object comparison will not work as most binding users would expect. If for instance we get 2 different ECalComponent objects ev1, ev2 that refer to the same logical event (identified by the same uid) then the comparison ev1==ev2 will return false.

To overcome this, the bindings should try to override the comparison operator where it is fit to do a semantic comparison rather than a mere object identifier comparison. Any exception to this rule should be reported since it probably is a bug in the binding.

Getting started

As a brief introduction we will present an example of a very simple app, a "calendar-grep" written in Ruby. This utility will grep the regular expression we feed it and present us a list of events that fullfill the regular expression (it will check for the summary field) and print some information about them. Nothing easier:

[1] require 'evolution'

     events=[]
     re=ARGV[0]
 [2] Evolution::get_esource_groups.each{|grp|
 [3]   grp.each{|src|
 [4]       cal=Evolution::ECal.new(src)
 [5]       events+=cal.select {|ev|                     
                                 ev.summary if ev.summary.to_a.select {|summary| summary.match(re)} != []
                        }
       }
     }
 
 [6] events.each { |ev|
        puts "#{ev.summary}\n\tDescription: #{ev.descriptions}\n\tAt: #{ev.location}\n\tStart: #{ev.dtstart}\n\tEnd: #{ev.dtend}"
     }

Let's see point by point what we are doing.

  • [1] This one is easy. We just load the evolution module and initialize the variables.
  • [2] Here we get a list of all the ESourceGroups present in the computer. ESourceGroups represent, somehow, "kind's" of calendars (they actually are more than that but for now it will suffice), so we will have one for Local calendars, one for Web calendars, etc. So basically what we are doing here is iterate over all the different kind of calendars we have in the system.
  • [3] ESourceGroups contain Esources wich contain info about present calendars in the computer. What we are doing here is iterate over all the calendars of one kind in the system (using the standard ruby idiom for iteration implemented as a ruby specific extension to the SWIG interface). Given the fact that in the outer iteration we were iterating over all kinds of calendars we are actually iterating over all the calendars in the system.
  • [4] We create a new ECal object passing it the ESource. This will actually open the calendar specified by the ESource (passing no ESource to the ECal constructor will open the system calendar)
  • [5] Here we use select (again a ruby idiom) wich will select all events contained in the calendar that fullfill the condition (similar to the list comprehension idiom in Python). Since summary is a mapping of an ECalComponentText it can be a String or an Array of String. Since we want to try to match (standard Ruby method) all the strings in the array we coerce it first to an Array with to_a. in the case summary was a String it will return as an array containing the string. In the case it was already an Array it will return itself. Note that we concatenate all events found in the select invocation with the events array. There are better Ruby idioms for doing this, but I preferred something easier to understand for non Ruby programmers.
  • [6] Iterate over the collected arrays and print them.

And that's all for a getting started guide :-)

API Reference

Evolution functions

The Evolution module has the following general use functions:

functions

 List get_esource_groups(): Returns a list of [[Evolution/SWIGForEDSTutorial#ESourceGroup_API |ESourceGroup]] objects representing all the [[Evolution/SWIGForEDSTutorial#ESourceGroup_API |ESourceGroups]] present in the system.

ECal API

The ECal class has the following public API:

methods:

        ECal(): ''Opens the default calendar.''
        ECal([[Evolution/SWIGForEDSTutorial#ESource_API |ESource]] src, bool create=false): Opens the calendar specified in src. The create flag determines if the calendar should be created 
                                               in case it does not exist.
        append([[Evolution/SWIGForEDSTutorial#ECalComponent_API |ECalComponent]] comp): Adds the component comp to the calendar
        del([[Evolution/SWIGForEDSTutorial#ECalComponent_API |ECalComponent]] comp): Deletes the component comp from the calendar
        del(string uid): Deletes the component identified by uid from the calendar.
        operator [](string uid): Retrieves the component identified by uid from the calendar.
        List get_list(): Returns the list of all the [[Evolution/SWIGForEDSTutorial#ECalComponent_API |ECalComponent]] objects stored in the calendar.
        string to_string: Returns a valid ical text representation of the calendar.

properties:

        int length: number of elements in the calendar.

ECalComponent API

The ECalComponent class has the following public API:

methods:

        ECalComponent(): creates an empty ECalComponent
        ECalComponent(string ical): creates an ECalComponent that wraps the ical component represented by the string
        ECalComponent(ECalComponent e): Copy constructor
        string to_string: Returns a valid ical text representation of the ECalComponent

properties:

        uid: String representing the ECalComponent uid
        url: String representing the ECalComponent url
        categories: Colon delimited string with a list of categories
        descriptions: Array of descriptions where each element may be an array of 2 strings or a string 
        comments: Array of comments where each element may be an array of 2 strings or a string 
        contacts: Array of contacts where each element may be an array of 2 strings or a string 
        created: Date of creation of the ECalComponent
        completed: Date for completion of the ECalComponent
        summary: String representing the summary of the ECalComponent
        dtend: Date marking the end of the ECalComponent
        dtstart: Date marking the beginning of the ECalComponent
        due: When the ECalComponent is due for
        dtstamp: Last time the ECalComponent was modified

ESource API

The ESource class has the following public API:

methods:

        ESource(string name, string uri, bool relative=true): Create an esource with the name and uri passed. Uri of the
                                                               Esource will be relative to it's parent [[Evolution/SWIGForEDSTutorial#ESourceGroup_API |ESourceGroup]] according to the relative flag
        string to_string(): Returns a string XML represention of the ESource (as can be seen in GConf)

properties:

        name: A String representing the name of the ESource
        relative: Boolean marking if the ESource uri is relative to its [[Evolution/SWIGForEDSTutorial#ESourceGroup_API |ESourceGroup]] base uri
        readonly: Boolean marking if the ESource is readonly or not
        uid: String representing the uid of the ESource
        uri: String representing the uri of the ESource
        relative_uri: String representing the uri of the ESource relative to it's [[Evolution/SWIGForEDSTutorial#ESourceGroup_API |ESourceGroup]]
        absolute_uri: String representing the absolute uri of the ESource
        group: The [[Evolution/SWIGForEDSTutorial#ESourceGroup_API |ESourceGroup]] to which this ESource belongs

ESourceGroup API

The ESourceGroup class has the following public API:

methods:

        ESourceGroup(string name, string uri): Create an ESourceGroup with the given name and uri.
        operator [](int n): Retrieves the nth [[Evolution/SWIGForEDSTutorial#ESource_API |ESource]] from the ESourceGroup
        insert(int index, ESource src): Insert the src at the position given by index
        append(ESource src): Append the source at the end

properties:

        readonly: boolean property marking if the group is readonly
        name: String representing the name of the ESourceGroup
        base_uri: String representing the base uri of the ESourceGroup
        uid: String representing the uid of the ESourceGroup
        int length: number of [[Evolution/SWIGForEDSTutorial#ESource_API |ESource]] objects in the ESourceGroup.

Apps/Evolution/SWIGForEDSTutorial (last edited 2013-08-08 22:50:11 by WilliamJonMcCann)