Eo Tutorial

Purpose

The purpose of this document is to explain how to work with Eo, how to port your code to Eo and what are the common pitfalls. It doesn't explain how it works inside.

Description

Eo is an Object oriented infrastructure for the EFL. It is a API/ABI safe library.

It supports inheritance, mixins, interfaces and composite objects.
Every class can implement functions from every other class.
It supports event signals, function overrides, private/protected/public/etc. variables and functions.

At the creation of the class, a "virtual table" is filled with the needed functions.
The key of this table is a (class id, function id) tuple.

eo_do() is invoked with a list of op ids and their parameters and is in charge to dispatch the relevant functions. Finding the correct function is fast because it is just a lookup table.

How to use it?

Important to know

How to create a class - H side?

How to create a class - C side?

Below, the object line as example.

#include "Eo.h"\n
EAPI Eo_Op \$(CLASS_NAME)_BASE_ID = EO_NOOP; // Initialisation of the class id to 0. Will be set dynamically by Eo itself.\n
#define MY_CLASS \$(CLASS_NAME)
...

Example for a developer function called by Eo:
This function receives the Eo object, the data corresponding to this class and the list of parameters.

static void
_foo(Eo *eo_obj, void *_pd, va_list *list)
{
int param_1 = va_arg(*list, int);
Eina_Bool param_2 = va_arg(*list, int);
Eina_Bool ret = va_arg(*list, Eina_Bool *);
foo_data obj = _pd;
if (ret) *ret = EINA_FALSE;
...
}

You can (not a must) implement a constructor. This constructor MUST call the parent constructor (eo_do_super()). It is the same for the destructor.
See eo_constructor() and eo_destructor().
If you don't have anything to do in constructor (like malloc, variables init...) or in destructor (free), don't implement them.

At the end of the file, you need to describe the class.
First, you need to supply the class constructor that sets the list of the functions that are implemented in this class. It includes functions overriden (constructor, destructor, member_add...) and functions specific to this class. If there is no function implemented in this class, you don't need a class constructor.
Then, you need a list to describe the new functions. For each one, the op id and a description.
Then, the class itself that consists in:

Finally, we define the class with:

Example (Evas Object Line):

#include "Eo.h"
EAPI Eo_Op EVAS_OBJ_LINE_BASE_ID = EO_NOOP;
#define MY_CLASS EVAS_OBJ_LINE_CLASS

...

static void
_line_xy_get(Eo *eo_obj, void *_pd, va_list *list)
{
const Evas_Object_Line *o = _pd;
Evas_Coord *x1 = va_arg(*list, Evas_Coord *);
Evas_Coord *y1 = va_arg(*list, Evas_Coord *);
Evas_Coord *x2 = va_arg(*list, Evas_Coord *);
Evas_Coord *y2 = va_arg(*list, Evas_Coord *);
Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJ_CLASS);
if (x1) *x1 = obj->cur.geometry.x + o->cur.x1;
if (y1) *y1 = obj->cur.geometry.y + o->cur.y1;
if (x2) *x2 = obj->cur.geometry.x + o->cur.x2;
if (y2) *y2 = obj->cur.geometry.y + o->cur.y2;
}
static void
_constructor(Eo *eo_obj, void *class_data, va_list *list EINA_UNUSED)
{
eo_do_super(eo_obj, eo_constructor());
Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJ_CLASS);
evas_object_line_init(eo_obj);
}
...
/* class constructor */
static void
_class_constructor(Eo_Class *klass)
{
const Eo_Op_Func_Description func_desc[] = {
/* Virtual functions of parent class implemented in this class */
EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_CONSTRUCTOR), _constructor),
EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_DESTRUCTOR), _destructor),
/* Specific functions to this class */
EO_OP_FUNC(EVAS_OBJ_LINE_ID(EVAS_OBJ_LINE_SUB_ID_XY_SET), _line_xy_set),
EO_OP_FUNC(EVAS_OBJ_LINE_ID(EVAS_OBJ_LINE_SUB_ID_XY_GET), _line_xy_get),
EO_OP_FUNC_SENTINEL
};
eo_class_funcs_set(klass, func_desc);
}
/* Descriptions for the functions specific to this class */
static const Eo_Op_Description op_desc[] = {
EO_OP_DESCRIPTION(EVAS_OBJ_LINE_SUB_ID_XY_SET, "Sets the coordinates of the end points of the given evas line object."),
EO_OP_DESCRIPTION(EVAS_OBJ_LINE_SUB_ID_XY_GET, "Retrieves the coordinates of the end points of the given evas line object."),
EO_OP_DESCRIPTION_SENTINEL
};
/* Description of the class */
static const Eo_Class_Description class_desc = {
"Evas_Object_Line",
EO_CLASS_DESCRIPTION_OPS(&EVAS_OBJ_LINE_BASE_ID, op_desc, EVAS_OBJ_LINE_SUB_ID_LAST),
NULL,
sizeof(Evas_Object_Line),
_class_constructor,
NULL
};
/* Definition of the class */
EO_DEFINE_CLASS(evas_object_line_class_get, &class_desc, EVAS_OBJ_CLASS, NULL);