Running a Juce app as Plugin in another Juce based app issues


#1

We have a host app made in Juce. This host app loads another Juce app/plugin through a .dll/.dylib
On Windows it seems to be running fine but i have issues on OSX.

When the plugin loads i get issues when a singleton is used. If will give a rassert because the singleton is already defined. The Dekstop instance is also already created and whever the Desktop class is looking for a specific component in my plugin i get an assertion that it can't be found.

 

void Desktop::componentBroughtToFront (Component* const c)

{

    const int index = desktopComponents.indexOf (c);

    jassert (index >= 0);

I can't imagine the same happens with Juce vst plugins loaded in a Juce audio host. Does someone know what the deal is here?
 

Some info on the setup:

Juce is compiled as a static library and linked to by both projects
The host has a DocumentWindow and loads the other app which also contains a DocumentWindow.
The Juce based plugin is of course not derived from JUCEApplication and calls initialiseJuce_GUI(); on initialization.

Any pointers on how to best approach this are welcome.


 

 

 


#2

Be careful if you're running a debug-build plugin in a debug-build host - sometimes the linker can get the symbols cross-linked so that global functions and symbols with the same name get mixed-up between the two binaries.


#3

Hi Jules, i tried it in release mode and a mix of modes but had no success yet. Will scale it down first to a minimal app to see wether i can get it working and than scale up (Mythbuster style) :-)


#4

Ok, i scaled down my project and this is what i found out.

When i link my two apps, host and plugin to the same static juce library i get all weird issues i mentioned in my original post.
As a test i created my host app trhough the introjucer (copying all needed modules to the host project) so it wouldn't use my static lib and when i start my plugin all runs fine. So no conflicts or weird issues.

Does anyone have an idea why the static lib approach does not seem to be working out?


#5

From a different project, I remember having similar issues: on Mac OS X any obj-c symbol is treated as global and always visible when linking to a static library.  See for example the very last section on this page:

https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/CppRuntimeEnv/Articles/SymbolVisibility.html

JUCE uses a handful of obj-c classes in various places. This means that when your plug-in refers to an obj-c symbol with the same name, it will use the obj-c symbol of the host, because it is already loaded in memory. However, this will most certainly go very bad as C++ symbols (aka not obj-c) will always be "private".

To understand this, consider the problem I faced in a previous project (which didn't use JUCE): I had a global static, yet unexported C++ variable which essentially was an Image Cache. A sub-class of NSView within both the host and the plug-in would access this image cache. What would happen though is that the plug-in would initialize the image cache with it's own images, and then call a method of the NSView sub-class, however, as the host had an obj-c class with the same name it would jump into the NSView of the host (as it was loaded first). The host's NSView, however, would access it's own copy of the Image Cache which didn't know anything about the plug-ins cached images and therefore would fail. Obviously, it's easy to think of other cases where things could end up in a crash.

For this particular project, I ended up adding the git commit hash to the end of the obj-c class name automatically and therefore the obj-c class name was now different in the plug-in and the host. However, another workaround seems to be to link to the .o object files direclty rather than linking to a static library. Obviously, there really shouldn't be any difference between linking to a bunch of .o files or to a static library of the same .o files, but it seems as if the Apple linker does some secret magic under the hood. Does anybody know any specifics or have some more experience with this?


#6

I just spoke to Jules: all the objective-c classes in JUCE are created dynamically with random class names at runtime to exactly avoid this problem. So the JUCE objective-c classes shouldn't be an issue.


#7

I think the your Image Cache example is comparable with the Desktop issue im having. I could try to link to the object files but that does not sound like fun. Could you show how that could that can be done in xcode, i'm not sure how to set this up. I found the juce .o files but i'm not sure where to set up the linker flags to actually linkt to those. In the meantime i'm open to other suggestions. 


#8

I added the .o files to my link binary libraries build step and it links and runs. But i still have the same issues. Why does this not seem to be a problem on Windows, what's the difference? 


#9
As a test i created my host app trhough the introjucer (copying all needed modules to the host project) so it wouldn't use my static lib and when i start my plugin all runs fine. So no conflicts or weird issues.

I don't really understand what you do differently here. The introjucer will just link all the .o files during the linking stage. It must be the way you compile your .cpp file: are you sure you are using identical compiler flags (for example -fvisibility=hidden is important for the bug you are seeing).


#10

You were right it was all about the visibility settings, i thought i had them all how they should be, i indeed found it weird why the modules approach worked and the static lib didn't. I walked through the different settings and compared how they were used in the a Juce audio plugin project. Now it builds and runs fine.
Thanx for your help.