[PD-dev] Passing creation arguments to newmethod

Christof Ressi info at christofressi.com
Thu Aug 5 23:32:30 CEST 2021


Hi Matt,

if you mix A_FLOAT / A_DEFFLOAT and A_SYM / A_DEFSYM in any Pd method 
definition (not just the "new" method!), the arguments are rearranged so 
that in the actual C function signature all the symbol arguments come 
first.

Here's an especially confusing example:

foo_class = class_new(s, (t_newmethod)foo_new, (t_method)foo_free,
         sizeof(t_foo), 0, A_DEFFLOAT, A_DEFSYM, A_DEFFLOAT, A_DEFSYM, 0);

becomes

static void *foo_new(t_symbol *arg2, t_symbol *arg4, t_floatarg arg1, 
t_float arg3);

> We ended up using A_GIMME,

Good choice :-) My personal advice: if you need to mix different 
argument types, better use A_GIMME.

---

Technical explanation: Pd methods take max. 5 type checked arguments. 
Without the optimization, there would be 32 possible function 
prototypes. Pd would not only have to declare them all, but also select 
the correct one at runtime, which would be very inefficient. With the 
optimization there are only 6 prototypes and you can simply select the 
appropriate one based on the number of symbol resp. gpointer arguments.

If you want to learn more, have a look at pd_typedmess() in in m_class.c.

Fun fact: pd_typedmess() often calls function pointers with more 
arguments than the original functions - which is undefined behavior. It 
just happens to work because in the default calling convention ("cdecl") 
the caller cleans up the stack. With other calling conventions where the 
*callee* has to clean up the stack, e. g. "stdcall", this would lead to 
stack corruption and crash horribly :-)

Christof

On 05.08.2021 20:22, Matt Barber wrote:
> Hi dev list,
>
> Question about the syntax of creation arguments and type checking. I 
> was working on an object yesterday, with the following setup line:
>
> grab_class = class_new(s, (t_newmethod)grab_new, (t_method)grab_free,
>         sizeof(t_grab), 0, A_DEFFLOAT, A_DEFSYM, 0);
>
> I'd assumed that it would require grab_new() to have this declaration 
> to match the order float, symbol as in class_new:
>
> static void *grab_new(t_floatarg f, t_symbol *s);
>
> but it only worked with the reverse:
>
> static void *grab_new(t_symbol *s, t_floatarg f);
>
> We ended up using A_GIMME, but for the future, is there a way to know 
> the order of parameters passed to the creator?
>
> Thanks,
> Matt
>
> _______________________________________________
> Pd-dev mailing list
> Pd-dev at lists.iem.at
> https://lists.puredata.info/listinfo/pd-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puredata.info/pipermail/pd-dev/attachments/20210805/367a58fd/attachment.htm>


More information about the Pd-dev mailing list