i’m doing some test using juce as a plugin (not matter which type), so i compiled juce as a shared library. In order to make things work, i discovered we need to create a message thread for processing when the shared library is loaded, and delete it when it gets unloaded.
If i do like this:
[code]#include “juce.h”
//================================================================================================
BEGIN_JUCE_NAMESPACE
extern void juce_callAnyTimersSynchronously();
extern Display* display;
extern bool juce_postMessageToSystemQueue (void* message);
END_JUCE_NAMESPACE
//================================================================================================
class SharedMessageThread : public Thread
{
public:
SharedMessageThread()
: Thread (T(“VstMessageThread”))
{
startThread (7);
}
~SharedMessageThread()
{
signalThreadShouldExit();
const int quitMessageId = 0xfffff321;
Message* const m = new Message (quitMessageId, 1, 0, 0);
if (! juce_postMessageToSystemQueue (m))
delete m;
while (isThreadRunning ());
clearSingletonInstance();
}
void run()
{
MessageManager* const messageManager = MessageManager::getInstance();
const int originalThreadId = messageManager->getCurrentMessageThread();
if (originalThreadId != getThreadId())
messageManager->setCurrentMessageThread (getThreadId());
printf ("SharedMessageThread::run started > %d > %d \n", originalThreadId, getThreadId());
while (! threadShouldExit()
&& messageManager->dispatchNextMessage())
{
}
printf ("SharedMessageThread::run finished \n");
if (originalThreadId != getThreadId())
messageManager->setCurrentMessageThread (originalThreadId);
printf ("SharedMessageThread::run cleanup \n");
}
// can we have more than one message thread ? NO !
juce_DeclareSingleton (SharedMessageThread, false)
};
juce_ImplementSingleton (SharedMessageThread);
//================================================================================================
void exportedMain () asm (“exportedMain”);
void exportedMain ()
{
initialiseJuce_GUI();
SharedMessageThread::getInstance();
DocumentWindow* c = 0;
{
const MessageManagerLock mml;
c = new DocumentWindow (T("xxx"), Colours::white, DocumentWindow::allButtons);
c->centreWithSize (400, 300);
c->setVisible (true);
}
Thread::sleep (2000);
{
const MessageManagerLock mml;
c->setVisible (false);
deleteAndZero (c);
}
Thread::sleep (500);
SharedMessageThread::deleteInstance();
shutdownJuce_GUI();
}
//================================================================================================
attribute((constructor)) void myPluginInit() // this is called when the library is unloaded
{
printf (“myPluginInit > %d \n”, Thread::getCurrentThreadId());
}
attribute((destructor)) void myPluginFini() // this is called when the library is unloaded
{
printf (“myPluginFini 1 > %d \n”, Thread::getCurrentThreadId());
}
[/code]
and i try to loadLibrary, executing the exportedMain function, all is working as expected, showing a white window, desappearing after some time and deallocating stuff.
But this doesn’t work if the exportedMain returns an object which lifetime cannot be guaranteed to finish upon its execution (think in the case of a VST plugin, which gets returned from the exported main function):
[code] // …
//================================================================================================
void exportedMain () asm (“exportedMain”);
void exportedMain ()
{
DocumentWindow* c = 0;
{
const MessageManagerLock mml;
c = new DocumentWindow (T("xxx"), Colours::white, DocumentWindow::allButtons);
c->centreWithSize (400, 300);
c->setVisible (true);
}
Thread::sleep (2000);
{
const MessageManagerLock mml;
c->setVisible (false);
deleteAndZero (c);
}
Thread::sleep (500);
}
//================================================================================================
attribute((constructor)) void myPluginInit() // this is called when the library is unloaded
{
printf (“myPluginInit > %d \n”, Thread::getCurrentThreadId());
initialiseJuce_GUI();
SharedMessageThread::getInstance();
}
attribute((destructor)) void myPluginFini() // this is called when the library is unloaded
{
printf (“myPluginFini 1 > %d \n”, Thread::getCurrentThreadId());
SharedMessageThread::deleteInstance();
shutdownJuce_GUI();
}
[/code]
this should be working, but i’m getting a segmentation fault upon deletion (this is the call stacktrace):
myPluginFini 2 >
*** glibc detected *** ../bin/load_debug: corrupted double-linked list: 0x08086f60 ***
======= Backtrace: =========
/lib/libc.so.6[0xb7dea227]
/lib/libc.so.6[0xb7debb57]
/lib/libc.so.6(cfree+0x7a)[0xb7debe2a]
/home/kraken/Projects/juce_break/bin/libdll_debug.so(_ZN4juce6StringD1Ev+0x29)[0xb7be9da9]
/home/kraken/Projects/juce_break/bin/libdll_debug.so(_ZN4juce16FreeTypeFontFace13FontNameIndexD1Ev+0x11)[0xb7c2a965]
/home/kraken/Projects/juce_break/bin/libdll_debug.so(_ZN4juce16FreeTypeFontFaceD1Ev+0x36)[0xb7c2a99e]
/home/kraken/Projects/juce_break/bin/libdll_debug.so(_ZN4juce10OwnedArrayINS_16FreeTypeFontFaceENS_20DummyCriticalSectionEE5clearEb+0x58)[0xb7c2b3be]
/home/kraken/Projects/juce_break/bin/libdll_debug.so(_ZN4juce10OwnedArrayINS_16FreeTypeFontFaceENS_20DummyCriticalSectionEED1Ev+0x19)[0xb7c2b437]
/home/kraken/Projects/juce_break/bin/libdll_debug.so(_ZN4juce17FreeTypeInterfaceD0Ev+0x61)[0xb7c2b93b]
/home/kraken/Projects/juce_break/bin/libdll_debug.so(_ZN4juce17DeletedAtShutdown9deleteAllEv+0xae)[0xb7bf0ccc]
/home/kraken/Projects/juce_break/bin/libdll_debug.so(_ZN4juce16shutdownJuce_GUIEv+0x16)[0xb7beec0a]
/home/kraken/Projects/juce_break/bin/libdll_debug.so(_Z12myPluginFiniv+0x41)[0xb7be835f]
/home/kraken/Projects/juce_break/bin/libdll_debug.so[0xb7be839a]
/home/kraken/Projects/juce_break/bin/libdll_debug.so[0xb7be8248]
/home/kraken/Projects/juce_break/bin/libdll_debug.so(_fini+0x18)[0xb7cf8a1c]
/lib/ld-linux.so.2[0xb7fdc2e1]
/lib/ld-linux.so.2[0xb7fdcbf6]
/lib/libdl.so.2[0xb7d82cb4]
/lib/ld-linux.so.2[0xb7fd75dd]
/lib/libdl.so.2[0xb7d8304b]
/lib/libdl.so.2(dlclose+0x2a)[0xb7d82ce4]
../bin/load_debug[0x8057a45]
../bin/load_debug(__gxx_personality_v0+0x30c)[0x804a9b4]
/lib/libc.so.6(__libc_start_main+0xe0)[0xb7d9bfc8]
../bin/load_debug(__gxx_personality_v0+0x1b9)[0x804a861]
i don’t know why is leaking. i’ve tried doing the same with other libraries (exported like this) and there is no apparent problem. what can be ? i need to sort this out !!!
ps. the code for loading the function back is:
#include "juce.h"
typedef void (*EXPORTEDFUNC)();
int main ()
{
initialiseJuce_NonGUI();
void* dll = Process::loadDynamicLibrary ("/home/kraken/Projects/juce_break/bin/libdll_debug.so");
EXPORTEDFUNC ex = (EXPORTEDFUNC) Process::getProcedureEntryPoint (dll, "exportedMain");
if (ex)
ex ();
Process::freeDynamicLibrary (dll);
shutdownJuce_NonGUI();
return 1;
}