How to get the type of a object method given a t_object* object and its methodname?

Shakeeb Alireza's icon

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

Luigi Castelli's icon

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

Shakeeb Alireza's icon

Thanks very much, Luigi. You are super helpful as always!

S

Shakeeb Alireza's icon

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

Luigi Castelli's icon

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

Shakeeb Alireza's icon

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

Luigi Castelli's icon

Yes, I absolutely agree with you, Shakeeb. This is confusing.
I am glad it's making sense now, though.

Best

- Luigi