Commit d04591c7 authored by T.J. Corona's avatar T.J. Corona
Browse files

Fix visibility issue for PluginClients in os x

parent 8c661a26
......@@ -34,6 +34,31 @@
#define SMTK_HAVE_CXX_11
#endif
// Issue:
// Dynamic cast is not just based on the name of the class, but also the
// combined visibility of the class on OSX. When building the hash_code of
// an object the symbol visibility controls of the type are taken into
// consideration (including symbol vis of template parameters). Therefore, if a
// class has a component with private/hidden vis then it cannot be passed across
// library boundaries.
//
// Solution:
// The solution is fairly simple, but annoying. You need to mark template
// classes intended for use in dynamic_cast with appropropriate visibility
// settings.
//
// TL;DR:
// This markup is used when we want to make sure:
// - The class can be compiled into multiple libraries and at runtime will
// resolve to a single type instance
// - Be a type ( or component of a types signature ) that can be passed between
// dynamic libraries and requires RTTI support ( dynamic_cast ).
#if defined(SMTK_MSVC)
#define SMTK_ALWAYS_EXPORT
#else
#define SMTK_ALWAYS_EXPORT __attribute__((visibility("default")))
#endif
// Define a pair of macros, SMTK_THIRDPARTY_PRE_INCLUDE and
// SMTK_THIRDPARTY_POST_INCLUDE, that should be wrapped around any #include
// for a third party header file. Mostly this is used to set pragmas that
......
......@@ -56,9 +56,9 @@ class PluginClient;
#ifndef SMTK_MSVC
template <typename Registrar, typename Manager, typename... T>
class PluginClient : public detail::PluginClient<Registrar, Manager>,
public detail::PluginClient<Registrar, T>...,
public PluginClientBase
class SMTK_ALWAYS_EXPORT PluginClient : public detail::PluginClient<Registrar, Manager>,
public detail::PluginClient<Registrar, T>...,
public PluginClientBase
{
public:
static std::shared_ptr<PluginClientBase> create();
......@@ -83,8 +83,8 @@ struct Sentinel
}
template <typename Registrar, typename Manager = detail::Sentinel, typename... T>
class PluginClient : public detail::PluginClient<Registrar, Manager>,
public PluginClient<Registrar, T...>
class SMTK_ALWAYS_EXPORT PluginClient : public detail::PluginClient<Registrar, Manager>,
public PluginClient<Registrar, T...>
{
public:
static std::shared_ptr<PluginClientBase> create();
......@@ -99,7 +99,7 @@ protected:
};
template <typename Registrar>
class PluginClient<Registrar, detail::Sentinel> : public PluginClientBase
class SMTK_ALWAYS_EXPORT PluginClient<Registrar, detail::Sentinel> : public PluginClientBase
{
public:
PluginClient()
......@@ -120,7 +120,7 @@ namespace detail
/// an API that only depends on the Manager type to the user, and we implement
/// it in detail::PluginClient.
template <typename Manager>
class PluginClientFor
class SMTK_ALWAYS_EXPORT PluginClientFor
{
public:
virtual ~PluginClientFor();
......@@ -149,7 +149,7 @@ PluginClientFor<Manager>::~PluginClientFor()
/// Registries. The lifetime of these Registries are therefore tethered to the
/// lifetime of the PluginClient, which lives in the plugin's library.
template <typename Registrar, typename Manager>
class PluginClient : public PluginClientFor<Manager>
class SMTK_ALWAYS_EXPORT PluginClient : public PluginClientFor<Manager>
{
public:
bool registerPluginTo(const std::shared_ptr<Manager>&) override;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment