How to get the type of a object method given a t_object* object and its methodname?
Hi,
I'm struggling to find the right function in the c-api to query if a method that isabout to be called via send message is a GIMME, A_LONG, ...
If I have a t_object* obj
of the target object with a t_symbol* methodname
(eg bang) and I'd like to get the type of the method (named by methodname
) what is the current documented way?
As an aside, I found in ext_obex.h, there an undocumented method which looked promising:
t_method_object *object_getmethod_object(t_object *x, t_symbol *methodname)
where t_method_object
is struct
which has a messlist_entry which is an single entry in a t_messlist
I tested as follows:
t_method_object* mobj = object_getmethod_object(obj, methodname);
t_messlist m_entry = mobj->messlist_entry;
post("MESSLIST_ENTRY method_name %s type %s", m_entry.m_sym->s_name,
m_entry.m_type);
I was able to get the name of the method (m_entry.m_sym
) but m_entry.m_type
was empty.
Given that this is undocumented, I wasn't hoping for much but is there a canonical way to do this?
Any help would be really really appreciated.
Shakeeb
I believe the function that you are looking for is defined in ext_obex.h and it is prototyped as follows:t_messlist *object_mess(t_object *x, t_symbol *methodname);
- Luigi
Thanks very much, Luigi. You are super helpful as always!
S
Unfortunately, I tried object_mess
and got the same result as before (an empty m_type
). I tried it with untyped and typed methods but in all cases, empty.
I'm surprised that m_type
in t_messlist
holds method type information, since it's a char[]
typedef struct messlist
{
struct symbol *m_sym; // Name of the message
method m_fun; // Method associated w/ the message
char m_type[MSG_MAXARG + 1]; // Argument type information
} t_messlist;
Since I'm interested in programmatically figuring out whether a method
is a A_GIMME
or not, i.e. typed or untyped. These are defined e_max_atomtypes
(see below) which also contains a remark recommending to use a long instead to represent the value: "While these values are defined in an enum
, you should use a long
to represent the value". Why is m_type
in t_messlist
then a char[]
and why is it empty? Now I'm totally confused...
/** the list of officially recognized types, including pseudotypes for
commas and semicolons. Used in two places: 1. the reader, when it reads
a string, returns long, float, sym, comma, semi, or dollar;
and 2. each object method comes with an array of them saying what types
it needs, from among long, float, sym, obj, gimme, and cant.
@ingroup atom
@remark While these values are defined in an enum, you should use a long to represent the value.
Using the enum type creates ambiguity in struct size and is subject to various inconsistent
compiler settings.
*/
typedef enum {
A_NOTHING = 0, ///< no type, thus no atom
A_LONG, ///< long integer
A_FLOAT, ///< 32-bit float
A_SYM, ///< t_symbol pointer
A_OBJ, ///< t_object pointer (for argtype lists; passes the value of sym)
A_DEFLONG, ///< long but defaults to zero
A_DEFFLOAT, ///< float, but defaults to zero
A_DEFSYM, ///< symbol, defaults to ""
A_GIMME, ///< request that args be passed as an array, the routine will check the types itself.
A_CANT, ///< cannot typecheck args
A_SEMI, ///< semicolon
A_COMMA, ///< comma
A_DOLLAR, ///< dollar
A_DOLLSYM, ///< dollar
A_GIMMEBACK, ///< request that args be passed as an array, the routine will check the types itself. can return atom value in final atom ptr arg. function returns long error code 0 = no err. see gimmeback_meth typedef
A_DEFER = 0x41, ///< A special signature for declaring methods. This is like A_GIMME, but the call is deferred.
A_USURP = 0x42, ///< A special signature for declaring methods. This is like A_GIMME, but the call is deferred and multiple calls within one servicing of the queue are filtered down to one call.
A_DEFER_LOW = 0x43, ///< A special signature for declaring methods. This is like A_GIMME, but the call is deferref to the back of the queue.
A_USURP_LOW = 0x44 ///< A special signature for declaring methods. This is like A_GIMME, but the call is deferred to the back of the queue and multiple calls within one servicing of the queue are filtered down to one call.
} e_max_atomtypes;
Any help figuring this out would be appreciated.
Thanks,
S
Hi Shakeeb,
I will share some code with you that hopefully will clear up your confusion.
Here is how you post to the Max window various methods that your object may support:
void myobj_printmess(t_myobj *x, t_symbol *methodname)
{
t_messlist *mess = object_mess((t_object *)x, methodname);
if (mess) {
object_post(NULL, "method name: %s, type: %d", mess->m_sym->s_name, mess->m_type[0]);
}
}
m_type[0]
holds one of the values defined in e_max_atomtypes.
I don't know why it is defined as a char. My guess would be that the t_messlist
data structure is a very old piece of code, and back at the time when it was written they were probably trying to minimize the memory footprint of the struct.
Please let me know if it works for you.
- Luigi
Thanks so much for your help and patience, Luigi. It totally makes sense now, but you can appreciate how this can be confusing (-:
I also find the mix of the public, private, documented, undocumented and deprecated methods in the c-api confusing (object_mess
is a case in point). I wonder if it would be possible to have a header file which contains only fully documented, public and non-deprecated methods.
I guess min-devkit
and min-api
( https://github.com/Cycling74/min-api) are trying to do this but I then again I suppose this is also another layer on top of the c-api which is unlikely to be rewritten.
S
Yes, I absolutely agree with you, Shakeeb. This is confusing.
I am glad it's making sense now, though.
Best
- Luigi