Juce_dll_build


#1

I made JUCE dll. I used JUCE_DLL_BUILD in dll and JUCE_DLL in my project.
I almost managed to make this work. However there are some build errors.

One issue is related to “juce::ModalCallbackFunction” I use this with enterModalState and showMenuAsync. Error is:
_error LNK2001: unresolved external symbol "public: static class juce::ModalComponentManager::Callback * __cdecl juce::ModalCallbackFunction::create(class std::function<void _cdecl(int)>)"

other one to OpenGL:
error LNK2001: unresolved external symbol __imp__glBegin@4

Actually I get many more errors but they are basically the same as those two.

Did I miss something or is this JUCE problem? Perhaps there is a workaround?


#2

Looks like you’re missing something related to a platform-specific implementation.


#3

I found, what problem was.

  1. class ModalCallbackFunction is missing JUCE_API attribute. After I added it problem was solved. I’m sure ROLI will add this missing attribute.
  2. I forget to add “#pragma comment(lib, “OpenGL32.Lib”)” to my application.

Now I have another problem. If I compile in “Release” everything works fine but in “Debug” I get debug heap assertion after adding ToolButtons to ToolBar. Assertion happens at end of Toolbar::addItemInternal call.

I believe this happens because debug heap is used (_malloc_dbg, _free_dbg). Unfortunately I’m not smart enough to figure out what to do. Perhaps someone could solve this because in “Release” build everything works really nice.


#4

After lots of testing I found that only 3 things are not working in “Debug” build:

  1. Adding ToolButtons to ToolBar
  2. My expression evaluator class
  3. Some OpenGL classes I use for drawing objects

My application is quite complex and those 3 things are just small part. I feel so close but I’m stuck in dark.
I tried adding “JUCE_LEAK_DETECTOR” to all juce classes without it but no success.


#5

Why do you need JUCE as a dll?


#6

It will appear on develop in a few minutes.


#7

Thank you fabian.

Several reasons why I want to use dll:

  1. Size of my binary is around 150 Mb. I want to split this to modules.
  2. Compile takes forever, linking even longer
  3. I need to use 64bit toolchain otherwise linker runs out of memory
  4. I have some support utilities for my application that also use JUCE and same dll could be used.

I located problem and it is in “Toolbar::addDefaultItems” function. This function creates an array in one dll and items are added by factory which is in second dll.
HeapBlock::realloc is called which uses “std::malloc” instead of “juceDLL_malloc” and I believe this is wrong.

I fixed problem by not using “addDefaultItems”. Instead I use this function:

void AddToolbarItems(juce::ToolbarItemFactory& factory, juce::Toolbar& toolBar)
{
	juce::Array<int> ids;
	factory.getDefaultItemSet(ids);
	toolBar.clear();
	for (auto itemId : ids)
	{
		if (auto* tc = toolBar.createItem(factory, itemId))
		{
			toolBar.insertToolbarItem(tc, -1);
		}
	}
	toolBar.resized();
}

I had to add insertToolbarItem to juce

void Toolbar::insertToolbarItem(ToolbarItemComponent* tc, int insertIndex)
{
	items.insert(insertIndex, tc);
	addAndMakeVisible(tc, insertIndex);
}

Everything seems to work for now. I even managed to fix OpenGL issues that I was having.

I would love to get comment from ROLI regarding this issue. Am I correct that std::malloc inside HeapBlock is cause for this issue and can you do anything about this? If not then at least add “insertToolbarItem” to JUCE like I did. Thank you.


#8

Ah, that sounds like an appropriate need for a dll.

However, have you tried organizing your code as a Single Compilation Unit? I was having problems with the linker taking forever, and switching to that format eliminated the problem. It’s basically a “hack” to do the linker’s job for it - all your code ends up in a single file to be compiled. JUCE modules are organized this way.

This also helps with compile times, since if you can isolate parts of your code that act as a unit into a SCU, you will only have to build it once.

If you do go the DLL route, beware of Singletons!


#9

How likely it is, that there is a hidden problem? For example, that everything works during testing but it fails randomly or under special condition?


#10

Using std::malloc is fine as long as all your dlls and exes use the same runtime. JUCE does not have a runtime/compiler agnostic ABI. Mixing and matching different runtimes/compilers will certainly result in many subtle bugs.

Ensuring a compiler agnostic ABI in JUCE would be very complex and is similar to the way the plug-in backends achieve this (for example, with a .COM like interface (VST3) or a plain-old-c interface with opcodes (VST2)).