Forums > Dev

message sent to an external is sent to several external of the same class

August 14, 2013 | 7:02 am

Hi,

I’m trying to use an custom external in a patcher, it’s in c++. You can send it some messages. It sort of works. Now if i create another object box ; invoke the same custome external class ; and send a message to the fisrt created one, the new one will receive those messages.

So, how is it possible ? At which level could those messages interfere ? Is there a set of "good practice rules" to avoid this, ie naming differently variables and messages to the max object ? or is that a problem related to c/c++ ?

sorry if i’m not clear… i’m uneasy with the vocabulary to use here


August 14, 2013 | 7:22 am

Hi,

I guess you’re a bit too generic here. Did you write the external? If yes, could you provide a MWE reproducing your bug?

If it’s a third-party code (and you can’t ask the developer), then it might be trickier. As a first guess, I’d search the code for any global variables that might be accessed by multiple instances simultaneously and check whether there was any interference there. If not, I’d check if the object gets registered to any notifications and I would try to examine the exact notifications to which the object is attached to. If none of this works, I’d crack my head against a wall in the hope that something useful comes to my mind…

HTH,
Ádám


August 14, 2013 | 8:19 am

Hi,

Thanks, i’ll crack my head against a wall right now ! ;)
I didn’t do it myself, it’s part of an internship i’m doing, so i have access to the source code, it’s a bit big, providing a MWE without the entire thing might be difficult (i’d prefer to avoid that, because i’m not sure i’m allowed to now, and several things need improvement). I think there are global variables, should be a lot of them. I thought… i thought even something global would stay "inside" its instance, not interfere…

And it seems solved ! At least better ! Indeed it was a global variable, ie declared outside of any function, inside a .cpp file, and once i declared in the "protected" part of the file’s header (related .h file) ; it doesn’t interfere anymore. So thanks a lot.
But… Is there a sort of general rule ? How can you be sure that a variable is declared inside an instance ? how does Max behave in regard to private/public/protected and namespace ?…. so many mysteries !

anyway thanks a lot. sorry for that "sorcerer’s apprentice" workflow…


August 14, 2013 | 12:18 pm

Hi,

indeed, the point of having global variables is that, once Max loads the bundle containing your external’s code, the variable would be alive until Max unloads the bundle (which at the moment may only happen when Max quits). This means that every instance of your object will "see" that variable. Moreover, even if you delete every instance of your object from your patcher, the global variable would still be there, so if you instantiate a new instance at some later point, it would still "see" the global variable with its lastly set value.

This can be useful if your external accesses a shared resource (eg. a network port), where you’d need to keep track of the state of the resource regardless of your actual instances. However, I usually stay away from global variables as long as I can, since (to my taste) they don’t fit quite nicely into the OO idea.

The description that Nicolas gave about the visibility of different stuff is pretty nice; I would only add that, in C++, you also have the option of declaring namespaces (indeed a very helpful concept), so you can isolate things also by declaring them within a custom namespace.

Cheers,
Ádám


August 14, 2013 | 2:17 pm

Thanks for

1. Everything global in your code is shared by all the ‘instances’ of your object (and that implies to care a bit more about multithreading).

2. Everything static in a compilation unit is local to that compilation unit { but } { and } it is shared also by all the ‘instances’ of your object.

3. If you want something { own by }{ local to } an instance you need to include his declaration in your object structure (and allocated the related memory in your ‘new’ method if it needs to).

4. You can mix all that and make complex scenarios (with C++ for instance in the scope) ; but at the end you can reduce the situation to that three cases.

and

indeed, the point of having global variables is that, once Max loads the bundle containing your external’s code, the variable would be alive until Max unloads the bundle (which at the moment may only happen when Max quits). This means that every instance of your object will "see" that variable. Moreover, even if you delete every instance of your object from your patcher, the global variable would still be there, so if you instantiate a new instance at some later point, it would still "see" the global variable with its lastly set value.

, things become clearer now. The culprit seemed to be that unprotected variable. I was wondering though, if that behaviour of global variables exist outside of Max – explaining : if i open twice the same application, which code contains some global variables, will they share said variables ?

Thanks again for your invaluable help !


August 14, 2013 | 3:21 pm

if i open twice the same application, which code contains some global variables, will they share said variables ?

No, they won’t. They are separate applications, having their own allocated memory blocks. What you need to understand here is that the bundle is loaded only once by Max. In this context, you may think of the bundle as an "application within the application". When you launch Max, it will not load any bundles (besides some system ones). Now, when you instantiate an object the first time, Max will load the bundle containing that object. From this point, the bundle resides in the memory as long as Max is running; therefore, all global variables, function tables etc. will remain in the memory. When Max loads the bundle, it will call the entry point of the bundle (which is the main() function). Therefore, this function will execute only once, at bundle-loading time, and is independent of any instance of your object. Then, each time when you instantiate a new instance of your object (including the very first time when you load it), Max will call the object initialisation function, which returns a pointer to your newly instantiated object. When you delete the object, Max will free this pointer; however, anything that is not related to that particular instance (eg. global variables, function tables etc) will stay in the memory of the Max application. But remember, this has nothing to do with an instance of any other running application (eg. if you run two instances of Max, they will operate with separated memory blocks, so a bundle loaded into one instance of Max will not "see" the one loaded by the "other Max"). Let me know if this is not clear at all…

Hope this helps,
Ádám


August 15, 2013 | 3:51 am

This is very clear and helps a lot ! Thanks.


August 16, 2013 | 5:49 am

Oh, ok. I understand everything now ! (kidding ;) )


Viewing 8 posts - 1 through 8 (of 8 total)