how add instance-local attributes on mop wrapper object?

diablodale's icon

Hi. What are APIs or process to add instance-local attributes on my mop wrapper object?

I see no object instance-local version of `max_jit_class_addattr()`
I tried and failed with `object_addattr(ptrWrapperObject, attr)`
I tried and failed with `object_addattr_format(...)`
Both of those fails were silent. No errors. And no attribute appeared on the object in the inspector.

Rob Ramirez's icon

hey Dale, I think you can simply use: max_jit_object_addattr(t_object *max_ob, void *attr)
passing in pointers to the max object wrapper and the attribute you wish to add.

diablodale's icon

No such API that I can find in headers of SDK 6.1.4 or max-api.
In addition, there is no such function exported in 6.1.4's: maxapi.lib or jitlib.lib
Perhaps it is private and un-exported?
If so, would you release the code for that API *if* the code within it uses publically exported apis?

Rob Ramirez's icon

my apologies it is indeed not exported.

can you try with:
jit_object_addattr((t_object *)x, attr);
object_attr_addattr_parse((t_object *)x, attr_name->s_name, "dynamicattr", gensym("long"), 0, "1");

diablodale's icon

No luck here. `jit_object_addattr()` isn't in the headers, but it is exported so I declared it as you wrote above before using it. I applied your two calls with `x` being a pointer to the max wrapper t_object (not the jitter t_object). No attribute appeared in the Max inspector.

I also tried an approach to add the "dynamicattr" attribute attribute on the attribute object before I object_addattr() on to the max wrapper t_object. Still no attribute appeared in the Max inspector.

FYI: In contrast, I have been using jit object attributes (object, not class) for some time. They work and I can use them as a workaround by traversing pointers between objects.

Rob Ramirez's icon

I think it's intentional that dynamic attrs don't show up in the inspector, but they should still function, and show up in the object attributes green arrow menu and in a connected attrui.

diablodale's icon

Nothing I can see in an attrui, or right-clicking on inlet 0.
I don't know what "green arrow menu" is. So I haven't checked there.

Aside from the above challenges, if the intention of this object attribute approach is to *not* have it appear in the inspector, then this approach won't work for my scenarios.

Unless you know otherwise, Max does not support adding visible object attributes directly on Max Wrapper objects. The alternatives that I've found so far that do work are:
1. Only add object attributes that are named and flagged with MAX_JIT_MOP_FLAGS_OWN_*****
2. Only add object attributes that are on the jitter object. Add them before max_jit_class_wrap_standard(). I have seen (undocumented and not tested long term) that I can do it after ...wrap_standard() if I make a call to max_jit_class_wrap_addmethods(). The latter seems to re-inspect the jitter object and expose public jitter attributes in the Max Wrapper.

Max Gardener's icon

You mean this, Rob? Never thought of the dot as green.

diablodale's icon

Hit a challenge. Is there a way to expose jit *object* attributes so that `attrname value` and `getattrname` messages to the wrapper function as usual?

In testing, I discovered that when jit object attributes are added, the max wrapper doesn't expose them for manipulation with those typical messages. Max stubbornly reports "doesn't understand attrname".

My guess is that max_jit_classex_standard_wrap() creates class methods on the max wrapper class for each of the public jit class attributes it finds. Therefore, since jit *object* attributes don't exist when wrap(), those methods that would have been made by wrap() on the Max wrapper don't exist. And therefore the wrapper "doesn't understand".

Idea #1 Challenge is with max wrapper object methods. According to the Max SDK 6.1.4, "instance methods are not actually fully implemented at this time". And the only API I see is object_addmethod(t_object *x, method m, C74_CONST char *name, ...) which has no DEFER/USURP_LOW functionality that would be needed for jitter object attributes.

Idea #2 Have a "catchall" *class* method on the max wrapper. And in that, I can check if the incoming message is for one of my jit object attributes. Though, unclear both on how I defer/usurp, and how to make a "catchall" class method.

Idea #3 From some shared vector<>, create max wrapper *class* methods with names matching "attrname" and "getattrname" and usurp/defer/low as needed, and have those methods call max_jit_attr_set() and max_jit_attr_getdump(). I create the jitter *object* attributes as I do today. And the later when a patch runs, my hope is that max_jit_attr_set() will correctly find the jitter object attribute because the attribute name will exist at that time.

Idea #4 Don't use object attributes on max wrappers or jitter objects due to issues in earlier posts + today's findings. Instead, create class attributes on jitter and/or max wrapper. And then *never* use the default getters/setters. I'll need to create my own collection of them for all the possible types (7 core + fixed arrays of them) that can work correctly in my dynamic/object instance scenarios. I loose dynamic attributes 😢. However, I can have fixed attributes that have dynamic locations of data in memory.

Other ideas or opinions?