Re: gpointer question



From what I have read, it looks like I can use a gpointer to add the 
data to my struct.  Unfortunately, I really do not understand how
(self taught, and not covered in my C books).

Here is an simplified example of what I would like to try:

typedef struct {
        int  model_id;
        int  active;
        int  units;
        typGeometry  geodata;
        gpointer  modeldata;
} typModel;

typdef struct {
       float length;
       float lwl;
       float beam;
       float draft;
       float depth;
} typShip;

So I want to get the gpointer in the typModel struct to point to the 
typShip struct.  The trick is that I do not
know the size of the struct pointed to until the assignemt at runtime 
(a designer may use the typMachine struct).

I dont know how you want to process the additional info struct, but the
following might help you:

typedef struct {
  int model_id;
  int active;
  int units;
  typeGeometry geodata;
} typModel;

typedef struct {
  typModel _base;
  float lwl;
  float beam;
  float draft;
  float depth;
} typShip;
  
So you dont add the additional info to your model, instead you make a
new derived model typ and add the base info to it (note: the base model
must be the first element in struct typShip!).

A few functions could look like this:

void model_init(typModel* model) {
  model->model_id = get_next_id();
  model->active = 1;
  /*...*/
}
typModel* model_new() {
  typModel* model = g_malloc0(sizeof(*model));
  model_init(model);
  return model;
}

void ship_init(typShip* ship) {
  model_init((typModel*)ship);
  ship->lwl = 5;
  ship->depth = 200;
  /*...*/
}
typShip* ship_new() {
  typShip* ship = g_malloc0(sizeof(*ship));
  ship_init(ship);
  return ship;
}

Now you can down/up cast from typShip<->typModel.
To use the derived structs (typShip) you either add a typ_id to your
base struct (typModel) and then:

  switch (model->typ_id) {
    CASE TYP_SHIP:
      ship = (typShip*)model;
      /* .. so something ...*/
      break;
  }

or the other way (which i think is nicer):
Add functions to you base struct:

  typedef void (*doSomethingFunc)(typModel*);

  struct _typModel {
    int model_id;
    /* .... */
    doSomethingFunc do_something;
  };

  static void do_something_ship(typShip* ship) {
    /* ... */
  }

  void ship_init(typShip* ship) {
    typModel model = (typModel*)ship;
    model_init(model);
    model->do_something = (doSomethingFunc)do_something_ship;
    /* ... */
  }

Now you just call 
  model->do_something(model);
and you dont need to know whether it is a ship or whatever...


Markus.





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]