Skip to content

Commit

Permalink
A sad workaround for a sad misery with Python bindings on Windows.
Browse files Browse the repository at this point in the history
  • Loading branch information
mosra committed Oct 23, 2019
1 parent d47bc8f commit 01d8cdd
Show file tree
Hide file tree
Showing 6 changed files with 15 additions and 8 deletions.
2 changes: 2 additions & 0 deletions doc/corrade-changelog.dox
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,8 @@ namespace Corrade {
- Global state used by @ref PluginManager::Manager, @ref Utility::Debug and
@ref Utility::Resource internals is no longer duplicated when Corrade is
built statically and linked to more than one dynamic library or executable.
This works on all platforms except for Python bindings on Windows at the
moment, where the workaround is to build Corrade dynamically.
- @ref PluginManager::Manager and @ref Utility::Debug now have the global
state thread-local when the @ref CORRADE_BUILD_MULTITHREADED option is
enabled (see also [mosra/corrade#65](https://github.com/mosra/corrade/issues/65))
Expand Down
4 changes: 2 additions & 2 deletions src/Corrade/PluginManager/AbstractManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,14 +219,14 @@ namespace {
Implementation::StaticPlugin*& windowsGlobalStaticPlugins() {
/* A function-local static to ensure it's only initialized once without any
race conditions among threads */
static Implementation::StaticPlugin** const uniqueGlobals = reinterpret_cast<Implementation::StaticPlugin**>(Utility::Implementation::windowsWeakSymbol("corradePluginManagerUniqueGlobalStaticPlugins"));
static Implementation::StaticPlugin** const uniqueGlobals = reinterpret_cast<Implementation::StaticPlugin**>(Utility::Implementation::windowsWeakSymbol("corradePluginManagerUniqueGlobalStaticPlugins", &corradePluginManagerUniqueGlobalStaticPlugins));
return *uniqueGlobals;
}

std::map<std::string, AbstractManager::Plugin*>*& windowsGlobalPlugins() {
/* A function-local static to ensure it's only initialized once without any
race conditions among threads */
static std::map<std::string, AbstractManager::Plugin*>*&(*const uniqueGlobals)() = reinterpret_cast<std::map<std::string, AbstractManager::Plugin*>*&(*)()>(Utility::Implementation::windowsWeakSymbol("corradePluginManagerUniqueGlobalPlugins"));
static std::map<std::string, AbstractManager::Plugin*>*&(*const uniqueGlobals)() = reinterpret_cast<std::map<std::string, AbstractManager::Plugin*>*&(*)()>(Utility::Implementation::windowsWeakSymbol("corradePluginManagerUniqueGlobalPlugins", reinterpret_cast<void*>(&corradePluginManagerUniqueGlobalPlugins)));
return uniqueGlobals();
}

Expand Down
2 changes: 1 addition & 1 deletion src/Corrade/Utility/Debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ namespace {
DebugGlobals& windowsDebugGlobals() {
/* A function-local static to ensure it's only initialized once without any
race conditions among threads */
static DebugGlobals&(*const uniqueGlobals)() = reinterpret_cast<DebugGlobals&(*)()>(Implementation::windowsWeakSymbol("corradeUtilityUniqueDebugGlobals"));
static DebugGlobals&(*const uniqueGlobals)() = reinterpret_cast<DebugGlobals&(*)()>(Implementation::windowsWeakSymbol("corradeUtilityUniqueDebugGlobals", reinterpret_cast<void*>(&corradeUtilityUniqueDebugGlobals)));
return uniqueGlobals();
}

Expand Down
11 changes: 8 additions & 3 deletions src/Corrade/Utility/Implementation/WindowsWeakSymbol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,23 @@

#include "WindowsWeakSymbol.h"

#include "Corrade/Utility/Assert.h"
#include <cstdio>

#define WIN32_LEAN_AND_MEAN 1
#define VC_EXTRALEAN
#include <windows.h>

namespace Corrade { namespace Utility { namespace Implementation {

void* windowsWeakSymbol(const char* name) {
void* windowsWeakSymbol(const char* name, void* backup) {
/* FARPROC?! I want either a function pointer or a variable pointer */
void* address = reinterpret_cast<void*>(GetProcAddress(GetModuleHandleA(nullptr), name));
CORRADE_INTERNAL_ASSERT(address);
/* This shouldn't fail, except in Python, where it's a sad, sad misery. */
if(!address) {
std::fprintf(stderr, "Cannot query global symbol %s and make it unique\n"
"across DLLs. App may misbehave, sorry. Build Corrade as dynamic as a workaround.\n", name);
address = backup;
}
return address;
}

Expand Down
2 changes: 1 addition & 1 deletion src/Corrade/Utility/Implementation/WindowsWeakSymbol.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

namespace Corrade { namespace Utility { namespace Implementation {

void* windowsWeakSymbol(const char* name);
void* windowsWeakSymbol(const char* name, void* backup);

}}}

Expand Down
2 changes: 1 addition & 1 deletion src/Corrade/Utility/Resource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ namespace {
ResourceGlobals& windowsResourceGlobals() {
/* A function-local static to ensure it's only initialized once without any
race conditions among threads */
static ResourceGlobals* const uniqueGlobals = reinterpret_cast<ResourceGlobals*>(Implementation::windowsWeakSymbol("corradeUtilityUniqueWindowsResourceGlobals"));
static ResourceGlobals* uniqueGlobals = reinterpret_cast<ResourceGlobals*>(Implementation::windowsWeakSymbol("corradeUtilityUniqueWindowsResourceGlobals", &corradeUtilityUniqueWindowsResourceGlobals));
return *uniqueGlobals;
}

Expand Down

0 comments on commit 01d8cdd

Please sign in to comment.