How to store a value that will be manipulated by many Max objects?

Joe Kaplan's icon

In general I'm curious what the best practice is for storing a value that several Max objects will need to be able to access and manipulate.

My particular usecase: There will be many instances of an object in my patch. I want each instance to auto-register in the notification system using object_register(). This requires me to generate a unique name for each instance of the object. To do this, I believe I need a way to keep a running count of how many instances exist. Each new instance of the object needs access to that counter.

t_symbol* seems like an obvious place to start. Since that is a piece of memory that is accessible to all max objects.

Say I have something like:
t_symbol* ObjectCount = gensym("1");

By casting ObjectCount->s_name from char* to int and back. I should be able to register my object with a name based on the current value of ObjectCount, then increment it, and then store the new value for the next instance to use.

The problem is that Object Count has to be initialized before it can be used. So before I can get the current value of the t_symbol I have to initialize the t_symbol. Otherwise I crash when trying to use ObjectCount because, within the object instance, I am using a variable that hasn't been initialized.

The result is that every time I create a new instance of the object I reset ObjectCount to it's initial value.

I'm still learning C++, so perhaps there's already a design pattern for this that I'm not familiar with. Or maybe t_symbol is the wrong direction in the first place? I thought I'd post here to see if anybody has any input as I continue with my own research. Please let me know if you have any thoughts.

Thanks!

Joe Kaplan's icon

Well, I worked this out! It turns out t_object* can be cast to and from other common types, like int or string. So all I have to do is store my object counter as s_thing, instead of s_name. t_symbol* is quite the clever omnitool. :)

        #include <cstring>
        
        c74::max::t_symbol* ObjectCounter = c74::max::gensym("ObjectCounter");
        if (!ObjectCounter->s_thing) {
            ObjectCounter->s_thing = (c74::max::t_object*)0;
        }
        int ObjectCount = (int)ObjectCounter->s_thing;
        string str = std::to_string(ObjectCount);
        const char* ObjectName = str.c_str();
        c74::max::object_register(c74::max::gensym("name_space"), c74::max::gensym(ObjectName), maxobj());
        ObjectCount++;
        ObjectCounter->s_thing = (c74::max::t_object*)ObjectCount;

Note that gensym() requires a const char* . Casting the int to const char* was not trivial. There are probably other ways, but I was able to use c_str() in the cstring library.

Also note that if this code appears in the constructor, the dummy instance will increment ObjectCount. So in this case, the first object you create will be named "1" even though ObjectCounter->s_thing is initialized to "0".

To avoid this, you can put the whole block above in an if condition: if (dummy() == false){....}