JUCE DLL with Components - how?

Hey everyone,
I encountered a little problem while trying to create a dynamic library with custom components in it.

I want to build a software which can be extended by plug-ins (not audio plug-ins). The users can build their own plug-ins (dynamic libraries) which can be loaded during runtime (by loading a JSON file containing the paths to the libraries).

The dynamic libraries expose a single function getCreator() which returns a Creator object which will be used in a factory design pattern. The Creator can create an object on demand, and this object has its own custom component, which will be displayed within the main program.

Within the library I call initialiseJuce_GUI(); otherwise the component won’t show and some assertions are thrown.

Creating the dynamic libraries works like a charm, however, once I add the component from the library to my main component, two things happen:

  1. Dynamic cast errors
    Now and then, I get a bunch of those errors displayed in the debug console:
    2019-12-19 15:41:20.039460+0100 vLEx[20744:1305019] dynamic_cast error 2: One or more of the following type_info's has hidden visibility. They should all have public visibility. N4juce9ComponentE, N4juce10TextButtonE, N4juce14TopLevelWindowE.
    The custom component has only a TextButton as a member so I guess the custom component might be the culprit.
  2. Leaking MouseCursors
    Once I move the mouse above the custom component, the LeakedObjectDetector throws an assertion:
Dangling pointer deletion! Class: MouseCursor
JUCE Assertion failure in juce_LeakedObjectDetector.h:66

The stack:

|#0|0x00000001006a18a9 in juce::LeakedObjectDetector<juce::MouseCursor>::~LeakedObjectDetector() at /Applications/JUCE/modules/juce_core/memory/juce_LeakedObjectDetector.h:66|
|---|---|
|#1|0x000000010051add5 in juce::LeakedObjectDetector<juce::MouseCursor>::~LeakedObjectDetector() at /Applications/JUCE/modules/juce_core/memory/juce_LeakedObjectDetector.h:50|
|#2|0x000000010051acd2 in juce::MouseCursor::~MouseCursor() at /Applications/JUCE/modules/juce_gui_basics/mouse/juce_MouseCursor.cpp:164|
|#3|0x00000001005020c5 in juce::MouseCursor::~MouseCursor() at /Applications/JUCE/modules/juce_gui_basics/mouse/juce_MouseCursor.cpp:161|
|#4|0x000000010051233e in juce::MouseInputSourceInternal::revealCursor(bool) at /Applications/JUCE/modules/juce_gui_basics/mouse/juce_MouseInputSource.cpp:507|
|#5|0x00000001005f0809 in juce::MouseInputSourceInternal::setScreenPos(juce::Point<float>, juce::Time, bool) at /Applications/JUCE/modules/juce_gui_basics/mouse/juce_MouseInputSource.cpp:295|
|#6|0x00000001005127a3 in juce::MouseInputSourceInternal::handleEvent(juce::ComponentPeer&, juce::Point<float>, juce::Time, juce::ModifierKeys, float, float, juce::PenDetails) at /Applications/JUCE/modules/juce_gui_basics/mouse/juce_MouseInputSource.cpp:340|
|#7|0x0000000100512492 in juce::MouseInputSource::handleEvent(juce::ComponentPeer&, juce::Point<float>, long long, juce::ModifierKeys, float, float, juce::PenDetails const&) at /Applications/JUCE/modules/juce_gui_basics/mouse/juce_MouseInputSource.cpp:634|
|#8|0x00000001005d28dd in juce::ComponentPeer::handleMouseEvent(juce::MouseInputSource::InputSourceType, juce::Point<float>, juce::ModifierKeys, float, float, long long, juce::PenDetails, int) at /Applications/JUCE/modules/juce_gui_basics/windows/juce_ComponentPeer.cpp:88|
|#9|0x0000000100679eb0 in juce::NSViewComponentPeer::sendMouseEvent(NSEvent*) at /Applications/JUCE/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm:701|
|#10|0x000000010067a6d1 in juce::NSViewComponentPeer::redirectMouseMove(NSEvent*) at /Applications/JUCE/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm:601|
|#11|0x0000000100676ef9 in juce::JuceNSViewClass::mouseMoved(objc_object*, objc_selector*, NSEvent*) at /Applications/JUCE/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm:1647|
|#12|0x00007fff36e6f367 in -[NSWindow(NSEventRouting) _reallySendEvent:isDelayedEvent:] ()|
|#13|0x00007fff36e6d667 in -[NSWindow(NSEventRouting) sendEvent:] ()|
|#14|0x00007fff36d0d3ab in -[NSApplication(NSEvent) sendEvent:] ()|
|#15|0x00007fff36cfb5c0 in -[NSApplication run] ()|
|#16|0x00000001003e1ef2 in juce::MessageManager::runDispatchLoop() at /Applications/JUCE/modules/juce_events/native/juce_mac_MessageManager.mm:343|
|#17|0x00000001003e1dc7 in juce::JUCEApplicationBase::main() at /Applications/JUCE/modules/juce_events/messages/juce_ApplicationBase.cpp:262|
|#18|0x00000001003e1bdc in juce::JUCEApplicationBase::main(int, char const**) at /Applications/JUCE/modules/juce_events/messages/juce_ApplicationBase.cpp:240|

It seems to be the same problem as this: Error "Dangling pointer deletion! Class: MouseCursor" when exporting Juce Component from DLL

What am I doing wrong? Every help is very much appreciated! :slight_smile:

Is that allowed by the license?

Rail

Good luck! I’ve tried doing exactly this myself, as an experiment.
My personal conclusion was that C++ sucks when it comes to dynamic libraries and I simply gave up.

1 Like

To add some (maybe) useful info, you could be able to make the custom Component show up in the application, but as soon as you try to do something with it (e.g. handling mouse events), you’re screwed and I believe there’s no workaround around this.

But how is an audio-plugin-host handling this to let the user interact with the GUI? is there a special interface forwarding the mouse events somehow?

The plugin GUIs are just normal operating system windows as far as the host is concerned.

Exactly. Passing objects is a completely different beast.

I see, so the host never actually get’s the mouse events as it’s handled by the operating system?

There she goes the idea of plug-ins with custom and embedded GUI… damn :smiley:

A follow-up question just to understand the limitations of dynamic libraries better: with objects do you mean the mouse events? I haven’t fully understand the underlying problem, yet.

By objects I mean the objects that are returned from your factory method. The first answer to this stackoverflow question may help you understand the issues better: https://stackoverflow.com/questions/22797418/how-do-i-safely-pass-objects-especially-stl-objects-to-and-from-a-dll

1 Like