basic question about calling a function

May 26, 2008 at 7:46am

basic question about calling a function

Dear all,

I’m cleaning a 2 years old code and, doh, it’s not pretty to see. This
is an object which is half a data manager and half a message center. I
use a lot of :

////////////////////////////////////////////////////////////////////////

t_atom *templist;

if (!init) initlcd(x); // make sure we got the lcd pointer

templist = x->l_templist;

typedmess(x->l_lcdobj, ps_recordsprite, 0L, 0); // remotely send message
to the lcd object

SETLONG(templist+0, xx-5);
SETLONG(templist+1, yy-5);
SETLONG(templist+2, xx+5);
SETLONG(templist+3, yy+5);
SETLONG(templist+4, 10);

typedmess(x->l_lcdobj, ps_paintoval, 5, templist);

////////////////////////////////////////////////////////////////////////

and so on, to build messages. But with dozen functions now, the code
goes to 800 lines and it is ridiculous to see all these repetitive tasks
that should be properly coded.

I’d love to build my ‘templist’ automatically, so i’m adding a simple
anything (list of everything) message building function. Something like :

////////////////////////////////////////////////////////////////////////

void setmess(t_sdmain *x, Symbol *s, int ac, Atom *av)
{
int i;
t_atom *templist;
templist = x->l_templist;

for (i=0;i
{
switch(av[i].a_type)
{
case A_LONG :
SETLONG(templist+i, av[i].a_w.w_long);
break;
case A_FLOAT :
SETFLOAT(templist+i, av[i].a_w.w_float);
break;
case A_SYM :
SETSYM(templist+i, av[i].a_w.w_sym);
break;
}
}
// just for debug
//outlet_anything(x->t_anyout, gensym(“mess”), ac, templist);

return(templist);
}
////////////////////////////////////////////////////////////////////////

I guess this is correct but i wonder about two things :

- how do i call it, really ? f.e in the first code sample of my post ?

- how do i manage memory if i don’t know what will be the length and
type of my pointer ? how do i reserve it and free it for safely ?

Sorry for these basic questions…

Many thanks in advance

f.e


f.e chanfrault | aka | personal computer music
>>>>>>> http://www.personal-computer-music.com
>>>>>>> | film soundtracks, sound art, music |

#38055
May 26, 2008 at 2:47pm

Part answer…

Your loop could be simplified as

for (i = 0; i < ac; i += 1)
{
templist[i] = av[i];
}

or for the hardcore C-fetishist

Atom* t = templist;
while (ac–) *t++ = *av++;
// at the end of this loop the original
// values of ac, t, and av are lost

Assignment is simply copying bits, there is no need to handle each atom type separately.

———————-

To allocate memory for your templist use memory allocation functions, either malloc() & Co. or the Max allocation API of getbytes() & Co. The malloc() family is more convenient but has a higher CPU overhead. For an array you would use the calloc() variant:

Atom* templist = (Atom*) calloc(ac, sizeof(Atom));

and, when you no longer need the memory:

free(templist);

Have you done memory allocation before? It’s typically covered fairly early in a programming course, but if you’re self-taught you may not have worked through the topic. I apologize, but I don’t remember how much programming experience you have.

#131961
May 26, 2008 at 2:51pm

In Max 5 there a bunch of a convenience functions for doing this sort
of thing (See below). If you are on a Mac then you can find the
headers in (and link against) the MaxAPI framework. On Windows, you
will have to wait. As previously mentioned, we are working hard on
the getting the API released.

The functions you are looking for are the ones like this:

/**
Convenience wrapper for object_method_typed() that passes a single
long integer as an argument.

@ingroup obj
@param x The object to which the message will be sent.
@param s The name of the method to call on the object.
@param v An argument to pass to the method.
@param rv The address of an atom to hold a return value.

@return A Max error code.
@see object_method_typed()
*/
t_max_err object_method_long(t_object *x, t_symbol *s, long v, t_atom
*rv);

/**
Convenience wrapper for object_method_typed() that passes an array of
long integers values as an argument.

@ingroup obj
@param x The object to which the message will be sent.
@param s The name of the method to call on the object.
@param ac The number of arguments to pass to the method.
@param av The address of the first of the array of arguments to
pass to the method.
@param rv The address of an atom to hold a return value.

@return A Max error code.
@see object_method_typed()
*/
t_max_err object_method_long_array(t_object *x, t_symbol *s, long ac,
long *av, t_atom *rv);

best,
Tim

On 2008 May 26, at 2:46 AM, f.e wrote:

> Dear all,
>
> I’m cleaning a 2 years old code and, doh, it’s not pretty to see.
> This is an object which is half a data manager and half a message
> center. I use a lot of :
>
> ////////////////////////////////////////////////////////////////////////
>
> t_atom *templist;
>
> if (!init) initlcd(x); // make sure we got the lcd pointer
>
> templist = x->l_templist;
>
> typedmess(x->l_lcdobj, ps_recordsprite, 0L, 0); // remotely send
> message to the lcd object
>
> SETLONG(templist+0, xx-5);
> SETLONG(templist+1, yy-5);
> SETLONG(templist+2, xx+5);
> SETLONG(templist+3, yy+5);
> SETLONG(templist+4, 10);
>
> typedmess(x->l_lcdobj, ps_paintoval, 5, templist);
>
> ////////////////////////////////////////////////////////////////////////
>
> and so on, to build messages. But with dozen functions now, the code
> goes to 800 lines and it is ridiculous to see all these repetitive
> tasks that should be properly coded.
>
> I’d love to build my ‘templist’ automatically, so i’m adding a
> simple anything (list of everything) message building function.

> Something like :
>
> ////////////////////////////////////////////////////////////////////////
>
> void setmess(t_sdmain *x, Symbol *s, int ac, Atom *av)
> {
> int i;
> t_atom *templist;
> templist = x->l_templist;
>
> for (i=0;i
> {
> switch(av[i].a_type)
> {
> case A_LONG :
> SETLONG(templist+i, av[i].a_w.w_long);
> break;
> case A_FLOAT :
> SETFLOAT(templist+i, av[i].a_w.w_float);
> break;
> case A_SYM :
> SETSYM(templist+i, av[i].a_w.w_sym);
> break;
> }
> }
> // just for debug
> //outlet_anything(x->t_anyout, gensym(“mess”), ac, templist);
>
> return(templist);
> }
> ////////////////////////////////////////////////////////////////////////
>
> I guess this is correct but i wonder about two things :
>
> – how do i call it, really ? f.e in the first code sample of my post ?
>
> – how do i manage memory if i don’t know what will be the length and
> type of my pointer ? how do i reserve it and free it for safely ?
>
> Sorry for these basic questions…
>
> Many thanks in advance
>
> f.e
>
> —
> f.e chanfrault | aka | personal computer music
> >>>>>>> http://www.personal-computer-music.com
> >>>>>>> | film soundtracks, sound art, music |

#131962
May 26, 2008 at 4:15pm

#131963

You must be logged in to reply to this topic.