Bug fixes for dynamic library builds (Windows)

Dynamic library builds and private inheritance are no friends. Here are a few instances that caused error C2385: ambiguous access of ‘delete’ and related errors on VS 2019. Below are my fixes that made it work (Juce 8.0.1). The issues poped up with or without JUCE_DLL_BUILD.

It might tmake sense to include a Windows DLL build with the testing routine to catch these early on.

juce_CaretComponent.h
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CaretComponent)

juce_Timer.cpp

struct LambdaInvoker final 
    : public Timer, public DeletedAtShutdown

juce_Midi_windows.cpp

struct Win32MidiService final 
    : public MidiServiceType, public Timer

JUCE_LEAK_DETECTOR (Win32MidiService)

juce_DragAndDropContainer.cpp
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DragImageComponent)

juce_TextEditor.cpp
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TextHolderComponent)

juce_CallOutBox.cpp

class CallOutBoxCallback final 
    : public ModalComponentManager::Callback,
      public Timer

juce_DropShadower.h

class JUCE_API  DropShadower  : public ComponentListener

class DropShadower::VirtualDesktopWatcher final  
    : public ComponentListener, public Timer

Sorry for bumping this up. I just had to redo all fixes manually after a Juce update.

I see that it may not be very common to use UI functions in a dynamic library. The use case here is to add capabilities to an application written in a language that can’t provide them natively. There are certainly other use cases. Since the fix is easy, I would appreciate if this could be merged.

I really think it’s not a good idea to pass any JUCE types across the boundaries of a dll.

Instead, I think you should put a C interface, or a very low level C++ interface (without JUCE types) around the DLL, and internally call all the JUCE functions, which IMO would solve your issues.

I’m not passing Juce types. There already is a C interface. I just need the code to compile.

Which version of JUCE are you trying that with?
Are you passing the JUCE_STANDALONE_APPLICATION=1 compile flag?

I’ve taken my DynamicLibrary example from here:

And added juce_gui_extra to the dll linkage. I even added a timer object and instantiated it - everything seems to build OK here.

I’ve updated the DynamicLibrary example above - tested on Mac + MSVC (VS 2022) and Clang on Windows.
Also added a timer to the dll call to make sure UI objects are correct.

Notice that:

  1. I don’t use JUCE_DLL_BUILD - I intentionally don’t want JUCE to export any of its symbols.

  2. I make sure to manually export only the functions that I intend to call from my own interface using extern "C" and DLLEXPORT which translates to __declspec (dllexport) on Windows, and nothing on Mac.

Thank you for looking into this.

JUCE_STANDALONE_APPLICATION is 0.

Disabling JUCE_DLL_BUILD doesn’t help though. You probably need to actually use (reference) UI objects in order for the compiler to throw the errors. Including the modules alone may not bring this up.

I did use them in my example, including instantiating a class inheriting Timer directly in the example from the DLL call. There’s no reason for those to fail as those inheritances aren’t exposed.

I would try compiling my example and compare what you’re doing differently that caused JUCE to expose those classes (and fail due to private inheritance, etc)

I second this. A JUCE plugin on windows is a DLL with only extern "C" functions exposed, and that usage definitely works. It would be helpful to know exactly how you’re configuring the build, and especially how it differs from a normal plugin build.

1 Like

There should only be extern "C" functions exposed because the standalone application that loads this DLL can’t handle anything else anyway. I might be inadvertently exposing symbols/functions that I’m not aware of.

It’s been years since I did this API. Will double-check. Thanks for the help.

Hi there,
on my end i also can’t get it to work. I created a dynamic library with Projucer from scratch, one simple h file and one extern “C” function doing nothing.

Library builds, i can use juce::DynamicLibrary to open the library but the function pointer is always NULL. lib.getFunction (“testFunc”) is always NULL.

What am i missing?

Tested on Juce 8.0.3

I just found the answer. Only the .h is not sufficient. One cpp file needs to be present, even if it is empty. Then the .h file will actually be compiled.

.h files are never compiled (unless they’re included in a .cpp file), so I assume that whatever your problem is is somewhere else.

If you read a bit up you’ll see a perfectly working example in my repo for a Dynamic Library. It is using CMake and not the Projucer though.

Thanks for your reply. There was another issue (on Mac). The Projucer sets all symbols to be hidden by default and i had to expose the one i needed explicitly. Now everything is working.