Tizen Native API
5.0
|
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 are unique.
Here we have a function to create a person 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 to free a person.
void
person_free(person *ptr) {
if (!EINA_MAGIC_CHECK(ptr, BASETYPE_MAGIC)) { EINA_MAGIC_FAIL(ptr, BASETYPE_MAGIC); return; }
- Note:
- EINA_MAGIC_FAIL is a macro that makes it easy to print an appropriate (and consistent) error message. Now knowing that ptr is indeed of type person we proceed to set EINA_MAGIC to EINA_MAGIC_NONE and free the allocated 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 it is 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 works:
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 for 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 EINA_UNUSED, char **argv EINA_UNUSED) { 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 obviously does not work since base is not a pilot:
print_pilot((pilot *)base); //BAD: fails (C cast prevents GCC warning)
print_pilot(sub);
That's all folks:
eina_shutdown(); }
See full source here.