Contents
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.