- Main Page
- Related Pages
- Modules
- Data Structures
- Files
- Examples

Whenever using Eina we must include it:

#include <Eina.h>

For this example we are going to define two classes, person and pilot, and since every pilot is a person we use inheritance. To be type safe we are going to add EINA_MAGIC to our classes:

#define BASETYPE_MAGIC 0x12345
struct _person {
EINA_MAGIC;
char *name;
};
typedef struct _person person;
#define SUBTYPE_MAGIC 0x3333
struct _pilot {
person base;
EINA_MAGIC;
char *callsign;
};
typedef struct _pilot pilot;

Note
  The values of BASETYPE_MAGIC and SUBTYPE_MAGIC have no meaning, the only important thing about them is that they be unique.

Here we have a function to create a perso given a name, nothing too fancy:

person *
person_new(const char *name)
{
person *ptr = malloc(sizeof(person));
EINA_MAGIC_SET(ptr, BASETYPE_MAGIC);
ptr->name = strdup(name);
return ptr;
}

And now the counterpart, a function the free a person.

void
person_free(person *ptr) {
Before we start releasing resources we check that the pointer we were given actually points to a person, and if not we will print an error message and quit:
if (!EINA_MAGIC_CHECK(ptr, BASETYPE_MAGIC))
{
EINA_MAGIC_FAIL(ptr, BASETYPE_MAGIC);
return;
}

Note
  EINA_MAGIC_FAIL is a macro that make's it easy to print an appropriate (and consistent) error message. Now knowing that ptr is indeed of type person we prooced to set EINA_MAGIC to EINA_MAGIC_NONE and free alocated memory:
  EINA_MAGIC_SET(ptr, EINA_MAGIC_NONE);
  free(ptr->name);
  free(ptr);
  }
  Setting EINA_MAGIC to EINA_MAGIC_NONE is important to prevent the struct from being used after freed.

Now we have our function to create a pilot, this one is a little more complex because we need to set EINA_MAGIC for the pilot and pilot->base, this is very important so that checking the EINA_MAGIC of (person*)my_pilot will work:

pilot *
pilot_new(const char *name, const char *callsign)
{
pilot *ptr = malloc(sizeof(pilot));
EINA_MAGIC_SET(ptr, SUBTYPE_MAGIC);
EINA_MAGIC_SET(&ptr->base, BASETYPE_MAGIC);
ptr->base.name = strdup(name);
ptr->callsign = strdup(callsign);
return ptr;
}

The function to free a pilot is not too different from the one that frees a person:

void
pilot_free(pilot *ptr) {
if (!EINA_MAGIC_CHECK(ptr, SUBTYPE_MAGIC))
{
EINA_MAGIC_FAIL(ptr, SUBTYPE_MAGIC);
return;
}
EINA_MAGIC_SET(ptr, EINA_MAGIC_NONE);
EINA_MAGIC_SET(&ptr->base, EINA_MAGIC_NONE);
free(ptr->base.name);
free(ptr->callsign);
free(ptr);
}

We also create functions to print a person or a pilot that check the type of the pointers they receive:

void
print_person(person *ptr)
{
if (!EINA_MAGIC_CHECK(ptr, BASETYPE_MAGIC)){
EINA_MAGIC_FAIL(ptr, BASETYPE_MAGIC);
return;
}
printf("name: %s\n", ptr->name);
}

And on to our main function where we declare some variables and initialize Eina:

void
print_pilot(pilot *ptr)
{
if (!EINA_MAGIC_CHECK(ptr, SUBTYPE_MAGIC)) {
EINA_MAGIC_FAIL(ptr, SUBTYPE_MAGIC);
return;
}
print_person(&ptr->base);
printf("callsign: %s\n", ptr->callsign);
}
int
main(int argc, char **argv)
{
person *base;
pilot *sub;
eina_init();

For Eina to be able to provide more informative error messages we are going to give names to our EINA_MAGIC types:

eina_magic_string_set(BASETYPE_MAGIC, "person");

Since our types won't live longer than the scope of the current function we can set the name without eina making a copy of the string:

eina_magic_string_static_set(SUBTYPE_MAGIC, "pilot");

Now we create a person, a pilot and print both as persons:

base = person_new("Tyrol");
sub = pilot_new("thrace", "starbuck");
print_person(base);
print_person((person *)sub);

Now we try to print both as pilots, which will obvisouly not work since base is not a pilot:

print_pilot(base); //BAD
print_pilot(sub);

That's all folks:

eina_shutdown();
}

See full source here.