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?
It seems like I should be able to do this but I can't figure out all the pointer bs.
-Jonathan
On 2012-11-14 02:17, Jonathan Wilkes 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?
It seems like I should be able to do this but I can't figure out all the pointer bs.
Something like (t_foo *)x->member, or ((t_bar *)x)->member?
Martin
Thanks Charles and Martin! I forgot the connection between pointers and array math-- that's very helpful.
Two questions below:
From: Martin Peach martin.peach@sympatico.ca To: Jonathan Wilkes jancsika@yahoo.com Cc: pd-dev List pd-dev@iem.at Sent: Wednesday, November 14, 2012 9:29 AM Subject: Re: [PD-dev] shared class data and functions
[...]
It seems like I should be able to do this but I can't figure out all the pointer bs.
Something like (t_foo *)x->member, or ((t_bar *)x)->member?
First, I noticed that I get a warning if I write the function to take an argument of type t_object *x and I send it one of type t_theobjectname *x. So I'm guessing I should probably go back to my function calls and explicitly cast to t_object*, is that right?
Second, (t_foo *)x->member will give me an error: "t_text has no member named x_member". I don't understand why, because the following works:
t_foo *blah = (t_foo *)x; blah->member etc...
-Jonathan
Martin
On 14/11/12 23:07, Jonathan Wilkes wrote:
Second, (t_foo *)x->member will give me an error: "t_text has no member named x_member". I don't understand
I guess it's precedence[0]?
(T *)x->m
equals:
(T *)(x->m)
when you really want:
((T *)x)->m
Claude
[0] http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Operator_precedence
Nevermind, I think I just figured it out by using another set of parentheses to so that the "x" gets cast before the -> operator.
Guess I'm just going to have to break down and get this pointer business straight. :)
Thanks again, Jonathan
----- Original Message -----
From: Jonathan Wilkes jancsika@yahoo.com To: Martin Peach martin.peach@sympatico.ca Cc: pd-dev List pd-dev@iem.at Sent: Wednesday, November 14, 2012 6:07 PM Subject: Re: [PD-dev] shared class data and functions
T hanks Charles and Martin! I forgot the connection between pointers and array math-- that's very helpful.
Two questions below:
From: Martin Peach martin.peach@sympatico.ca To: Jonathan Wilkes jancsika@yahoo.com Cc: pd-dev List pd-dev@iem.at Sent: Wednesday, November 14, 2012 9:29 AM Subject: Re: [PD-dev] shared class data and functions
[...]
It seems like I should be able to do this but I can't figure out
all the
pointer bs.
Something like (t_foo *)x->member, or ((t_bar *)x)->member?
First, I noticed that I get a warning if I write the function to take an argument of type t_object *x and I send it one of type t_theobjectname *x. So I'm guessing I should probably go back to my function calls and explicitly cast to t_object*, is that right?
Second, (t_foo *)x->member will give me an error: "t_text has no member named x_member". I don't understand why, because the following works:
t_foo *blah = (t_foo *)x; blah->member etc...
-Jonathan
Martin
Pd-dev mailing list Pd-dev@iem.at http://lists.puredata.info/listinfo/pd-dev
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