[PD] A_CANT (was: thread about args in an external, just look up and you'll probably see it there)

Jonathan Wilkes jancsika at yahoo.com
Tue May 27 00:49:01 CEST 2014


On 05/26/2014 04:48 PM, Miller Puckette wrote:
> So probably best just to leave it unfixed.  I think lots of folks maintaining
> librares wouldn't want someone else to come in and edit stuff for them.

Well in the case of Hans-maintained libs the only question is whether 
Hans wants to do it.  Those original maintainers are long gone.  I think 
it's a good idea because it turns a crasher into a run-time "no method" 
error, and people are already sending around "dsp" messages to toggle audio.

For everyone else, here's my hastily written RAQ (rarely asked 
questions).  If I'm wrong about anything please feel free to correct me...

What's the deal?

There's an atomtype named A_CANT.  Based on external source code from 
svn, only Miller and a few others previously understood what it is for.  
Based on looking at the source code, no one previously understood what 
it did.

What is A_CANT?

It's a special atom type.  It lets you add a method to a class while 
instructing Pd not to allow that method to be called using Pd's standard 
message passing system.

How is that different than A_NULL?

A_NULL can be used to tell Pd that a method does not accept any 
arguments.  For example, if you have a method called with the selector 
"reset" and it doesn't require any arguments, you can use A_NULL when 
adding that method in your class's setup routine. Theoretically, you 
might end up with something like this:

     class_addmethod(foo_class, (t_method)foo_reset, gensym("reset"), 
A_NULL, 0);

That tells Pd not to expect any atoms after the selector "reset". The 
way Pd is implemented, the user doesn't actually get an error if they 
send a message with arguments like "reset foo bar"-- it just silently 
truncates them.

In real code, however, you will just see something more like this

     class_addmethod(foo_class, (t_method)foo_reset, gensym("reset"), 0);

because the final "0" is the way to tell Pd "no more args, please". 
Since we didn't specify any in the first place, it is equivalent to 
writing "A_NULL" followed by the "0".

On the other hand, A_CANT would tell Pd that the "reset" message should 
not be handled at all by the message passing system:

     class_addmethod(foo_class, (t_method)foo_reset, gensym("reset"), 
A_CANT, 0);

In this case if the user sends a "reset" message to an object where the 
corresponding method has been set with an A_CANT argument, Pd will 
refuse and output a "bad arguments" error no matter what arguments you 
give it.  (Note: only for the most recent git revision-- older versions 
will just pass the argument on.)

When would you ever want to use A_CANT?

In situations where you want to define a method but don't want Pd's 
normal message passing system to access it.

A prime example is Pd's audio engine-- audio objects need a "dsp" method 
to process a block of audio, but an entire chain of objects must get 
processed on a regular schedule.  (I am guessing) Pd's normal message 
passing/parsing system creates too much overhead for that task.  So 
instead, Pd builds a big array of pointers to dsp methods when you turn 
on audio, and it iterates through the array every dsp tick.  Instead of 
passing messages, each method reads/writes to an array of samples.

Then why don't audio objects ever use A_CANT?

Miller's core audio objects now do.  Previously, however, they didn't, 
and so everyone followed suit.  That is, up to now every external 
developer has written their audio objects with a "dsp" method like this:

     class_addmethod(osc_class, (t_method)osc_dsp, gensym("dsp"), 0);

But as stated above, this is equivalent to an A_NULL argument. While it 
will restrict any arguments from being passed with a "dsp" message, it 
still allows the user to send a "dsp" message to the object from within 
Pd.  So, if [osc~] has a "dsp" method that expects arguments that are 
pointers to arrays of samples, but instead a user sends it a "dsp" 
message without any arguments, you can guess that the code there won't 
work correctly.  You will get a crash if you (purposely or accidentally) 
happen to do [dsp(--[osc~].

I'm an external developer.  What should I do?

Find the setup routine for all of your tilde objects, and for the dsp 
method add an "A_CANT, " before the terminating zero.  (If you already 
have an A_CANT there then you should brag so that people can admire your 
awesomeness.)

So:
     class_addmethod(osc_class, (t_method)osc_dsp, gensym("dsp"), 0);
becomes:
     class_addmethod(osc_class, (t_method)osc_dsp, gensym("dsp"), 
A_CANT, 0);

That will change a potential crasher bug to a user's runtime error.

-Jonathan

> cheers
> M
>
>




More information about the Pd-list mailing list