On Wed, Nov 14, 2012 at 1:17 AM, Jonathan Wilkes jancsika@yahoo.com wrote:
I have three classes: foo, bar, bow
Foo has a function:
void foo_blah(t_foo *x, t_symbol *s, t_int argc, t_atom *argv) { if(x->x_member == 1) do_something... }
Bar and bow both have x->x_member, too, and I want all three to use the same function so I don't have to copy it two more times. Is there a way to do this:
void foo_blah(t_pd *x, t_symbol *s, t_int argc, t_atom *argv) { if we can cast x to t_foo, t_bar or t_bow then check if x has x->member equal to 1, and if so then do_something...
}
which I can call by sending t_foo, t_bar or t_bow as the first arg to that function?
Pd classes are nested data structures. To be consistent and use this trick to your advantage, define your classes' data structures to have a parent data structure. Note that t_object is another name for t_text. This is all in m_pd.h.
t_pd<-t_gobj<-t_text
You define the first element of your class struct as a t_object or t_text. Then, you can cast any pointer to an instance of your class as a t_text *. Likewise, every t_text pointer can be cast as a g_obj *. Same for t_gobj * to t_pd *
Now, in order to have foo, bar, and bow have the same data structure element "member", create this class:
struct _parent { t_object my_object; //Does this name matter? t_int member; } t_parent;
Then, your other classes work the same way: pointers to foo, bar and bow can be cast as pointers to t_parent. Then, you're absolutely sure that ((t_parent *)x)->member exists and can be read/written.
If you don't like that approach--just make sure the "t_int member" occurs first after t_object in your class definitions to all three. The compiler turns accessing member into pointer arithmetic. For example, struct xyz { int x; int y; int z; } t_xyz;
t_xyz data; t_xyz *instance=&data;
The compiler turns instance->x into *((int *)instance) instance->y into *((int *)instance + 1) instance->z into *((int *)instance + 2)
So you see why member needs to be in the same location in each class.
Chuck