Inheritance in SSTS is interesting, it follows the same paradigm as GObject .
In the header file the structs that will define the object are difened along with the functions that operate on the object.
Foo.h
#ifndef __H_FOO__ #define __H_FOO__ #include "baseobject.h" #include <stdbool.h> typedef struct _FooClass FooClass; typedef struct _Foo Foo; typedef struct _FooPrivate FooPrivate; //the private data is defined in the .c file struct _FooClass { SBaseObjectClass parent_class; // The parent class holds the methods of the object CompFunc some_method; // Some method associated with the object. }; struct _Foo { SBaseObjectInstance parent; FooPrivate * priv; };
This was the declaration of the the data structures.
Then we need some functions to operate on the objects:
Foo * foo_new (char * my_str); void foo_free (Foo * self); bool foo_comp (Foo * self, char * other_str); void foo_set_str (Foo * self, char * new_str); #endif //__H_FOO__
In the .c file we define the real functions and methods to be used with the object. It is a littl fidely at first but when the objet is in place it should be ready to use.
Remeber, never trust anyone elses code.
Foo.c
#include "Foo.h" struct _FooPrivate { char * my_str; //The private data. }; void foo_deinit_method (Foo * self); // Prototype the deinit method. void foo_to_string_method (Foo * self); // Prototype the to_string method. bool foo_comp_method (char * str1, char * str2); // Prototype the comp method //The constructor Foo * foo_new (char * my_str) { Foo * self = malloc ( sizeof (Foo)); FooClass * klass = malloc( sizeof (FooClass)); s_base_object_set_class (self, klass); s_base_object_initize (self); s_base_object_set_deinit_method (self, foo_deinit_method); s_base_object_set_to_string_method (self, foo_to_string_method); klass->some_method = foo_comp_method; return self; } void foo_free (Foo * self) { s_base_object_free (self); // Calls foo_deinit_method } bool foo_comp (Foo * self, char * other_str) { FooClass * klass = (FooClass *) s_base_object_get_class (self); return klass->some_method (self->priv->my_str, other_str); } void foo_set_str (Foo * self, char * new_str) { free (self->priv->my_str); self->priv->my_str = s_string_new (new_str); }
Now we are almost done, the only things that remain is to write the methods. but first we have to go through what the code does.
In the constructor foo_new
we first create a pointer to
an instance of the object and an instance of the object class. The class
is then set to the object instance using the
s_base_object_set_class
function. It is important to set
the objects class before you initize the object.
After the class is set the object is initized, this adds the standard
deinit, ref, unref
and to_string
methods.
We then have to set our own to_string
and deinit
methods using the s_base_object_set_to_string_method,
and s_base_object_set_deinit_method
.
In the start of the C
-file we wrote some prototypes or
declarations of these methods, now it is time to implement them.
void foo_deinit_method (Foo * self) { FooClass klass = (FooClass *) s_base_object_get_class (self); free(self->priv->my_str); free(klass); free(self); } void foo_to_string_method (Foo * self) { return self->priv->my_str; } bool foo_comp_method (char * str1, char * str2) { if ( strcmp ( str1, str2 ) == 0 ) { return true; } else { return false; } }
And that is it.
Please note that not any of the objects in the system are thread-safe, and probably never will be.