From 8002b2d26e0191ec562fe2f5f2f42f51b03e9c30 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Mon, 11 Apr 2016 22:19:25 +0200 Subject: special case luabridge for windows/MSVC luabridge uses static fn addresses to identify classes. Windows uses different addresses for *identical* static functions in libardour.dll and ardour.exe This solves the issue by moving the all functions from a header-only implementation into libardour. --- libs/ardour/luabindings.cc | 92 ++++++++++++++++++++++++++++++++++- libs/lua/LuaBridge/detail/ClassInfo.h | 10 ++++ libs/lua/LuaBridge/detail/Userdata.h | 4 ++ tools/luadevel/wscript | 13 ++--- 4 files changed, 112 insertions(+), 7 deletions(-) diff --git a/libs/ardour/luabindings.cc b/libs/ardour/luabindings.cc index cf429ea5d7..a475416c19 100644 --- a/libs/ardour/luabindings.cc +++ b/libs/ardour/luabindings.cc @@ -38,6 +38,7 @@ #include "ardour/interthread_info.h" #include "ardour/lua_api.h" #include "ardour/luabindings.h" +#include "ardour/luaproc.h" #include "ardour/meter.h" #include "ardour/midi_track.h" #include "ardour/midi_port.h" @@ -55,6 +56,96 @@ #include "LuaBridge/LuaBridge.h" +#ifdef PLATFORM_WINDOWS +/* luabridge uses addresses of static functions/variables to identify classes. + * + * Static symbols on windows (even identical symbols) are not + * mapped to the same address when mixing .dll + .exe. + * So we need a single point to define those static functions. + * (normally they're header-only in libs/lua/LuaBridge/detail/ClassInfo.h) + * + * Really!! A static function with a static variable in a library header + * should never ever be replicated, even if it is a template. + * But then again this is windows... what else can go wrong. + */ + +template +void const* +luabridge::ClassInfo::getStaticKey () +{ + static char value; + return &value; +} + +template +void const* +luabridge::ClassInfo::getClassKey () +{ + static char value; + return &value; +} + +template +void const* +luabridge::ClassInfo::getConstKey () +{ + static char value; + return &value; +} + +void* +luabridge::getIdentityKey () +{ + static char value; + return &value; +} + +/* ...and this is the ugly part of it. + * + * We need to foward declare classes from gtk2_ardour. + * This is needed because some of the classes use objects from libardour + * as function parameters and the .exe would re-create symbols for libardour + * objects. + * + * Classes which don't use libardour symbols could be moved to + * gtk2_ardour/luainstance.cc, but keeping this here reduces code + * duplication and does not give the compiler a chance to even think + * about replicating the symbols. + */ + +#define CLASSKEYS(CLS) \ + template void const* luabridge::ClassInfo< CLS >::getStaticKey(); \ + template void const* luabridge::ClassInfo< CLS >::getClassKey(); \ + template void const* luabridge::ClassInfo< CLS >::getConstKey(); + +#define CLASSINFO(CLS) \ + class CLS; \ + template void const* luabridge::ClassInfo< CLS >::getStaticKey(); \ + template void const* luabridge::ClassInfo< CLS >::getClassKey(); \ + template void const* luabridge::ClassInfo< CLS >::getConstKey(); + +CLASSINFO(MarkerSelection); +CLASSINFO(TrackSelection); +CLASSINFO(TrackViewList); +CLASSINFO(TimeSelection); +CLASSINFO(RegionSelection); +CLASSINFO(PublicEditor); +CLASSINFO(Selection); +CLASSINFO(ArdourMarker); + +namespace Cairo { + class Context; +} +CLASSKEYS(Cairo::Context); +CLASSKEYS(std::vector); +CLASSKEYS(std::list); +CLASSKEYS(std::bitset<47ul>); // LuaSignal::LAST_SIGNAL +CLASSKEYS(ArdourMarker*); +CLASSKEYS(ARDOUR::RouteGroup); +CLASSKEYS(ARDOUR::LuaProc); + +#endif // end windows special case + /* Some notes on Lua bindings for libardour and friends * * - Prefer factory methods over Contructors whenever possible. @@ -582,7 +673,6 @@ LuaBindings::common (lua_State* L) .addFunction ("output_map", (ARDOUR::ChanMapping (PluginInsert::*)(uint32_t) const)&PluginInsert::output_map) .addFunction ("set_input_map", &PluginInsert::set_input_map) .addFunction ("set_output_map", &PluginInsert::set_output_map) - .endClass () .deriveWSPtrClass ("AutomationControl") diff --git a/libs/lua/LuaBridge/detail/ClassInfo.h b/libs/lua/LuaBridge/detail/ClassInfo.h index 8639dbec52..2a0ab001fd 100644 --- a/libs/lua/LuaBridge/detail/ClassInfo.h +++ b/libs/lua/LuaBridge/detail/ClassInfo.h @@ -36,6 +36,15 @@ template class ClassInfo { public: +#ifdef PLATFORM_WINDOWS + /* static symbols on windows (even identical symbols) are not + * mapped to the same address when mixing .dll + .exe. + * the implementation is moved to libardour/gtk2_ardour. + */ + static void const* getStaticKey (); + static void const* getClassKey (); + static void const* getConstKey (); +#else /** Get the key for the static table. The static table holds the static data members, static properties, and @@ -69,5 +78,6 @@ public: static char value; return &value; } +#endif }; diff --git a/libs/lua/LuaBridge/detail/Userdata.h b/libs/lua/LuaBridge/detail/Userdata.h index c7ee3bac3e..a0bbf720d4 100644 --- a/libs/lua/LuaBridge/detail/Userdata.h +++ b/libs/lua/LuaBridge/detail/Userdata.h @@ -51,11 +51,15 @@ 6. Our metatables have "__metatable" set to a boolean = false. 7. Our lightuserdata is unique. */ +#ifdef PLATFORM_WINDOWS +extern void* getIdentityKey (); +#else inline void* getIdentityKey () { static char value; return &value; } +#endif /** Interface to a class pointer retrievable from a userdata. diff --git a/tools/luadevel/wscript b/tools/luadevel/wscript index 5f5b46b5d1..3190380091 100755 --- a/tools/luadevel/wscript +++ b/tools/luadevel/wscript @@ -33,13 +33,14 @@ def build(bld): if bld.is_defined('WINDOWS_VST_SUPPORT') and bld.env['build_target'] != 'mingw': return + if bld.env['build_target'] != 'mingw': # TEST/DEVEL TOOL ####################### - obj = bld (features = 'cxx c cxxprogram') - obj.source = 'devel.cc' - obj.target = 'devel' - obj.uselib = ['SIGCPP', 'READLINE'] - obj.use = ['liblua'] - obj.install_path = None + obj = bld (features = 'cxx c cxxprogram') + obj.source = 'devel.cc' + obj.target = 'devel' + obj.uselib = ['SIGCPP', 'READLINE'] + obj.use = ['liblua'] + obj.install_path = None ######################################### # commandline luasession wrapper -- cgit v1.2.3