Forums > Dev

working w/ typedmess

September 10, 2006 | 11:52 pm

Hi all – I’m bashing my head against the wall a little bit trying to determine exactly how to specify/define a reference to the ‘receiver’ object in a call to typedmess().

I’ve been looking at the following code from Peter on the forums, which is helpful but not quite enough for me to connect all the dots.

void
ForwardAnything(
Symbol* iRecip,
Symbol* iMsg,
short iArgC,
Atom iArgV[])

{
static Symbol* sSymThrough = NIL;

Object* thing = (Object*) iRecip->s_thing;

// Initialize our static symbol first time through
if (sSymThrough == NIL)
sSymThrough = gensym("through");

// Make sure we have a vaild thing
if (thing == NIL)
return; // no good
if (thing->o_magic != MAGIC)
return; // also no good
if (ob_class(thing)->c_sym != sSymThrough)
return; // last check

// If we make it to here, we’re good to go
typedmess(thing, iMsg, iArgC, iArgV);

}

I’m trying to set up something simple like:

Symbol* existingObSym = gensym("existingOb");
Object* existingObject;
existingObject = (Object*)existingObSym->s_thing;
typedmess( existingObject, gensym( "do_it" ), 0, 0L );

but I don’t quite see how s_thing is used to bind the object properly. Please excuse my imprecise question – I just don’t know exactly what to ask…

Thanks for any help.


September 11, 2006 | 7:02 am

Here’s what you want to do, if you want to use this strategy
(although I’m not sure it’s the best):

In the receiver object, you need to set the s_thing member of the
t_symbol struct to a pointer to your receiver object. For instance,
in your new() method:

t_symbol *mySymbol = gensym("_private_symbol");
mySymbol->s_thing = x;

Because Max’s symbol table persists, you can now check the s_thing
member of gensym("_private_symbol") and retrieve the pointer to your
existing object, use typedmess, etc.

The problem with this strategy: symbols are stored in a global symbol
table. So if you have more than one receiver object, it will
overwrite the value of s_thing in its new method, presuming it uses
the same gensym("_private_symbol").

You might want to also look at the obex objects and the
object_register(), object_attach(), object_detach() and object_notify
() methods (documented in the pattr SDK, part of the normal SDK
download), since these provide much of the functionality you’re
looking for, based on what you’ve written.

jb

Am 11.09.2006 um 01:52 schrieb Liam Staskawicz:

> I’m trying to set up something simple like:
>
> Symbol* existingObSym = gensym("existingOb");
> Object* existingObject;
> existingObject = (Object*)existingObSym->s_thing;
> typedmess( existingObject, gensym( "do_it" ), 0, 0L );
>
> but I don’t quite see how s_thing is used to bind the object
> properly. Please excuse my imprecise question – I just don’t know
> exactly what to ask…
>
> Thanks for any help.


September 11, 2006 | 8:41 am

On 11-Sep-2006, at 9:02, Jeremy Bernstein wrote:
> In the receiver object, you need to set the s_thing member of the
> t_symbol struct to a pointer to your receiver object. For instance,
> in your new() method:
>
> t_symbol *mySymbol = gensym("_private_symbol");
> mySymbol->s_thing = x;
>
> Because Max’s symbol table persists, you can now check the s_thing
> member of gensym("_private_symbol") and retrieve the pointer to
> your existing object, use typedmess, etc.

What I would just add to the scenario sketched above is something like

t_symbol* mySymbol = gensym("_private_symbol");

if (mySymbol->s_thing == NIL)
mySymbol->s_thing = x;
else {
error("myClass: symbol _private_symbol already in use");
return; // or however you want to continue
}

I don’t recall if there is written documentation that a symbol’s
s_thing component is initialized to NIL, but it must be the case.

If you’re using the prefix-dot convention for naming your objects (as
in lp.abbie, tl.butterbp~, v.abs, etc.) I would extend that to naming
your private symbols (stas.privateSymbol or whatever). Or you can
generate a unique symbol. There’s a function in jitlib that does
this, but it’s not hard to roll your own if you need to be
independent of Jitter.

For all of that, Jeremy’s suggestion to use object_registry() & Co.
is perhaps the way of the future.

Hope this helps,
Peter

————– http://www.bek.no/~pcastine/Litter/ ————-
Peter Castine +–> Litter Power & Litter Bundle for Jitter
Universal Binaries on the way
iCE: Sequencing, Recording &
Interface Building for |home | chez nous|
Max/MSP Extremely cool |bei uns | i nostri|
http://www.dspaudio.com/ http://www.castine.de


September 11, 2006 | 8:52 pm

Hmm – I guess that splits my question into 2:

1. For the old s_thing strategy, the thing I still don’t understand is what form the reference to the existing object should take in the code for the sending object. How much do I need to know about it at compile time, and where do I need to specify that?

2. The pattr SDK sure presents a whole lot of new stuff to learn…just starting to go through that a bit now. If you would indulge another question, is the pattr SDK still the way to go if I want to be sending things bidirectionally between two objects, as opposed to a one-way client kind of thing? Is it easy to summarize the pros/cons for these two approaches? Sure appreciate the help – thanks again.


September 12, 2006 | 12:43 pm

On 11-Sep-2006, at 22:52, Liam Staskawicz wrote:

> 1. For the old s_thing strategy, the thing I still don’t understand
> is what form the reference to the existing object should take in
> the code for the sending object. How much do I need to know about
> it at compile time, and where do I need to specify that?

I don’t think there’s anything to know at compile time.

At run time the sender must check that mySymbol->s_thing:

- Is not null,
- that it what it points to is an object,
- (semi-optional) The object is the class you want it to be

This is what the sequence of conditions in the code you quoted does.
Once you know s_thing is an object, you can send messages to it. If
you include step 3, then you (the programmer, not the compiler) knows
what messages the object will understand.

All the aspiring recipient has to do as point the s_thing to itself,
viz:

MyObjBindToSymbol(tMyObj* me, tSymbol* iSym)
{
iSym->s_thing = me;
}

As in my previous, you are advised to first check that the symbol is
not already bound to a different object with something like

if (iSym->s_thing == NIL) {
// go ahead and bind…
}
else // maybe post an error() or something

>
> 2. The pattr SDK sure presents a whole lot of new stuff to learn…

Sure does. Sorry, can’t help with your question on this one.

– P.

————– http://www.bek.no/~pcastine/Litter/ ————-
Peter Castine +–> Litter Power & Litter Bundle for Jitter
Universal Binaries on the way
iCE: Sequencing, Recording &
Interface Building for |home | chez nous|
Max/MSP Extremely cool |bei uns | i nostri|
http://www.dspaudio.com/ http://www.castine.de


September 18, 2006 | 7:32 am

Thanks again for your help Peter and Jeremy. I’ve played around with this a bit, and was able to get up and running with typedmess( ), but am starting in on the obex path. I have a couple questions:

1. I’ve successfully been able to broadcast data via object_notify( ), although at this point this issue is more of a curiousity than anything (since it’s working) – but when I attach the client using object_attach( ), I do not get an expected t_max_err return value. Basically, I would expect to get MAX_ERR_NONE or one of the other -1 thru -4 error #defines that the obex objects use, but instead I get a large positive integer – 76436112. As I mentioned, the broadcast works just fine so this does not seem to be immediately critical, but I’d sure like to understand what’s happening there. Any thoughts?

2. What’s the best way for my original registered sender object to object_attach( ) to the original client object? Ultimately, I’ll want the client to broadcast things back to the ‘sender’, as well as continue to receive.
I object_register( ) the ‘sender’ in its new( ) routine, and object_attach( ) the client in its new( ) routine. But, not knowing exactly which order they’re likely to be instantiated in, what’s the best way to make sure they find each other for bidirectional communication?

Thanks again!


September 18, 2006 | 9:33 am

Am 18.09.2006 um 09:32 schrieb Liam Staskawicz:

> 1. I’ve successfully been able to broadcast data via object_notify
> ( ), although at this point this issue is more of a curiousity than
> anything (since it’s working) – but when I attach the client using
> object_attach( ), I do not get an expected t_max_err return value.
> Basically, I would expect to get MAX_ERR_NONE or one of the other
> -1 thru -4 error #defines that the obex objects use, but instead I
> get a large positive integer – 76436112. As I mentioned, the
> broadcast works just fine so this does not seem to be immediately
> critical, but I’d sure like to understand what’s happening there.
> Any thoughts?

object_attach doesnt’s return a t_max_err, but rather a pointer to
the registered object (the object referred to by the name_space and
name arguments). If you need to test for successful attachment,
simply make sure that this return value is not NULL. You shouldn’t
need the pointer for normal use.

> 2. What’s the best way for my original registered sender object to
> object_attach( ) to the original client object? Ultimately, I’ll
> want the client to broadcast things back to the ‘sender’, as well
> as continue to receive.
> I object_register( ) the ‘sender’ in its new( ) routine, and
> object_attach( ) the client in its new( ) routine. But, not
> knowing exactly which order they’re likely to be instantiated in,
> what’s the best way to make sure they find each other for
> bidirectional communication?

If you trigger the attach in a "loadbang" method, it’s guaranteed
that the entire patch has been instantiated. Assuming that your
sender registers itself in new() (as you mention), it should be ready
to go by the time your object gets its loadbang.

Alternately, set up a qelem in your client object: when the object
loads, it looks for the sender and attaches to it. If it can’t find
the sender, it sets the qelem and keeps trying (and resetting the
qelem as necessary) until the sender appears.

jb


September 19, 2006 | 12:18 am

Thanks for the sanity check on the return value from object_attach( )…

The qelem sounds like as good a strategy as any – thanks again.


September 19, 2006 | 1:37 am

Oh, I see now why I thought object_attach() should return a t_max_err – that’s what it says in the pattrsdk.pdf (page 37).

Is that a change that is not reflected in the doc?


September 19, 2006 | 9:20 am

Probably just an oversight. Thanks, I’ll fix this.

jb

Am 19.09.2006 um 03:37 schrieb Liam Staskawicz:

> Is that a change that is not reflected in the doc?


Viewing 10 posts - 1 through 10 (of 10 total)