Skip to content

Commit

Permalink
BUG: Explicitly instantiate common MetaDataObjects
Browse files Browse the repository at this point in the history
Certain configurations of shared libraries with hidden symbols can
produce different runtime identifications of the same object when
exported or instantiated in different libraries. This causes a failure
of the dynamic_cast. Explicitly instantiate the MetaDataObject to have
application level consistent runtime information.

ITK_TEMPLATE_EXPORT was remove because it was not functional and could
not have been used by anyone.

Change-Id: Idd58f373fdeebaaedbb5844f002962a67e47b598
  • Loading branch information
blowekamp committed Jun 10, 2014
1 parent 63f8b4b commit b72726c
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 101 deletions.
62 changes: 0 additions & 62 deletions Modules/Core/Common/include/itkMacro.h
Original file line number Diff line number Diff line change
Expand Up @@ -556,68 +556,6 @@ itkTypeMacro(newexcp, parentexcp);
#define ITK_FRIEND_TEMPLATE_FUNCTION_ARGUMENT(T)
#endif

//=============================================================================
/* Choose a way to prevent template instantiation on this platform.
- ITK_TEMPLATE_DO_NOT_INSTANTIATE = use #pragma do_not_instantiate to
prevent instantiation
- ITK_TEMPLATE_EXTERN = use extern template to prevent instantiation
*/
#if defined( __INTEL_COMPILER ) && __INTEL_COMPILER >= 700
#define ITK_TEMPLATE_EXTERN 1
#elif defined( __GNUC__ ) && __GNUC__ >= 3
#define ITK_TEMPLATE_EXTERN 1
#elif defined( _MSC_VER )
#define ITK_TEMPLATE_EXTERN 1
#endif
#if !defined( ITK_TEMPLATE_DO_NOT_INSTANTIATE )
#define ITK_TEMPLATE_DO_NOT_INSTANTIATE 0
#endif
#if !defined( ITK_TEMPLATE_EXTERN )
#define ITK_TEMPLATE_EXTERN 0
#endif

/* Define a macro to explicitly instantiate a template.
- ITK_TEMPLATE_EXPORT(X) =
Explicitly instantiate X, where X is of the form N(a1[,a2...,aN]).
examples: ITK_TEMPLATE_EXPORT(1(class Foo<int>))
ITK_TEMPLATE_EXPORT(2(class Bar<int, char>))
Use one level of expansion delay to allow user code to have
a macro determining the number of arguments. */
#define ITK_TEMPLATE_EXPORT(x) ITK_TEMPLATE_EXPORT_DELAY(x)
#define ITK_TEMPLATE_EXPORT_DELAY(x) template ITK_TEMPLATE_##x;

/* Define a macro to prevent template instantiations.
- ITK_TEMPLATE_IMPORT(X) =
Prevent instantiation of X, where X is of the form N(a1[,a2...,aN]).
examples: ITK_TEMPLATE_IMPORT(1(class Foo<int>))
ITK_TEMPLATE_IMPORT(2(class Bar<int, char>))
Use one level of expansion delay to allow user code to have
a macro determining the number of arguments.
*/
#if ITK_TEMPLATE_EXTERN
#define ITK_TEMPLATE_IMPORT_DELAY(x) extern template ITK_TEMPLATE_##x;
#elif ITK_TEMPLATE_DO_NOT_INSTANTIATE
#define ITK_TEMPLATE_IMPORT_DELAY(x) \
ITK_TEMPLATE_IMPORT_IMPL(do_not_instantiate ITK_TEMPLATE_##x)
#define ITK_TEMPLATE_IMPORT_IMPL(x) _Pragma(#x)
#endif
#if defined( ITK_TEMPLATE_IMPORT_DELAY )
#define ITK_TEMPLATE_IMPORT(x) ITK_TEMPLATE_IMPORT_DELAY(x)
#define ITK_TEMPLATE_IMPORT_WORKS 1
#else
#define ITK_TEMPLATE_IMPORT(x)
#define ITK_TEMPLATE_IMPORT_WORKS 0
#endif

//=============================================================================

/* Define macros to export and import template instantiations for each
library in ITK. */
#define ITK_EXPORT_ITKCommon(c, x, n) \
ITK_EXPORT_TEMPLATE(ITKCommon_EXPORT, c, x, n)
#define ITK_IMPORT_ITKCommon(c, x, n) \
ITK_IMPORT_TEMPLATE(ITKCommon_EXPORT, c, x, n)

//--------------------------------------------------------------------------------
// Helper macros for Template Meta-Programming techniques of for-loops
// unrolling
Expand Down
63 changes: 36 additions & 27 deletions Modules/Core/Common/include/itkMetaDataObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@

#include "itkMetaDataDictionary.h"
#include "itkMacro.h"
#include "itkCommand.h"
#include "itkFastMutexLock.h"
#include "itkArray.h"
#include "itkMatrix.h"

#include <cstring>

Expand Down Expand Up @@ -178,37 +178,46 @@ inline bool ExposeMetaData(const MetaDataDictionary & Dictionary, const std::str

const MetaDataObjectBase::ConstPointer baseObjectSmartPointer = Dictionary[key];

if ( baseObjectSmartPointer.IsNull() || strcmp( typeid( T ).name(), baseObjectSmartPointer->GetMetaDataObjectTypeName() ) != 0 )
MetaDataObject< T > const * const TempMetaDataObject = dynamic_cast< MetaDataObject< T > const * >( baseObjectSmartPointer.GetPointer() );
if ( TempMetaDataObject == ITK_NULLPTR )
{
return false;
}
{
MetaDataObject< T > const * const TempMetaDataObject = dynamic_cast< MetaDataObject< T > const * >( baseObjectSmartPointer.GetPointer() );
if ( TempMetaDataObject != ITK_NULLPTR )
{
outval = TempMetaDataObject->GetMetaDataObjectValue();
}
else
{
return false;
}
}

outval = TempMetaDataObject->GetMetaDataObjectValue();
return true;
}

// Specializations
template <> ITKCommon_EXPORT void MetaDataObject< unsigned char >::Print( std::ostream & os ) const;
template <> ITKCommon_EXPORT void MetaDataObject< char >::Print( std::ostream & os ) const;
template <> ITKCommon_EXPORT void MetaDataObject< signed char >::Print( std::ostream & os ) const;
template <> ITKCommon_EXPORT void MetaDataObject< unsigned short >::Print( std::ostream & os ) const;
template <> ITKCommon_EXPORT void MetaDataObject< short >::Print( std::ostream & os ) const;
template <> ITKCommon_EXPORT void MetaDataObject< unsigned int >::Print( std::ostream & os ) const;
template <> ITKCommon_EXPORT void MetaDataObject< int >::Print( std::ostream & os ) const;
template <> ITKCommon_EXPORT void MetaDataObject< unsigned long >::Print( std::ostream & os ) const;
template <> ITKCommon_EXPORT void MetaDataObject< long >::Print( std::ostream & os ) const;
template <> ITKCommon_EXPORT void MetaDataObject< float >::Print( std::ostream & os ) const;
template <> ITKCommon_EXPORT void MetaDataObject< double >::Print( std::ostream & os ) const;
template <> ITKCommon_EXPORT void MetaDataObject< std::string >::Print( std::ostream & os ) const;
#ifndef ITK_TEMPLATE_EXPLICIT_MetaDataObject
// Explicit instantiation is required to ensure correct dynamic_cast
// behavior across shared libraries.
#if defined( ITKCommon_EXPORTS )
// don't use export
#define ITKCommon_EXPORT_EXPLICIT
#else
// only import/hidden
#define ITKCommon_EXPORT_EXPLICIT ITKCommon_EXPORT
#endif
extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< bool >;
extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< unsigned char >;
extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< char >;
extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< signed char >;
extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< unsigned short >;
extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< short >;
extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< unsigned int >;
extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< int >;
extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< unsigned long >;
extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< long >;
extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< float >;
extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< double >;
extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< std::string >;
extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< Array<char> >;
extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< Array<int> >;
extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< Array<float> >;
extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< Array<double> >;
extern template class ITKCommon_EXPORT_EXPLICIT MetaDataObject< Matrix<double> >;
#undef ITKCommon_EXPORT_EXPLICIT
#endif

} // end namespace itk

Expand Down
31 changes: 19 additions & 12 deletions Modules/Core/Common/src/itkMetaDataObject.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,29 @@
* limitations under the License.
*
*=========================================================================*/
#define ITK_TEMPLATE_EXPLICIT_MetaDataObject
#include "itkMetaDataObject.h"

namespace itk
{

ITK_NATIVE_TYPE_METADATAPRINT( unsigned char );
ITK_NATIVE_TYPE_METADATAPRINT( char );
ITK_NATIVE_TYPE_METADATAPRINT( signed char );
ITK_NATIVE_TYPE_METADATAPRINT( unsigned short );
ITK_NATIVE_TYPE_METADATAPRINT( short );
ITK_NATIVE_TYPE_METADATAPRINT( unsigned int );
ITK_NATIVE_TYPE_METADATAPRINT( int );
ITK_NATIVE_TYPE_METADATAPRINT( unsigned long );
ITK_NATIVE_TYPE_METADATAPRINT( long );
ITK_NATIVE_TYPE_METADATAPRINT( float );
ITK_NATIVE_TYPE_METADATAPRINT( double );
ITK_NATIVE_TYPE_METADATAPRINT( std::string );
template class ITKCommon_EXPORT MetaDataObject< bool >;
template class ITKCommon_EXPORT MetaDataObject< unsigned char >;
template class ITKCommon_EXPORT MetaDataObject< char >;
template class ITKCommon_EXPORT MetaDataObject< signed char >;
template class ITKCommon_EXPORT MetaDataObject< unsigned short >;
template class ITKCommon_EXPORT MetaDataObject< short >;
template class ITKCommon_EXPORT MetaDataObject< unsigned int >;
template class ITKCommon_EXPORT MetaDataObject< int >;
template class ITKCommon_EXPORT MetaDataObject< unsigned long >;
template class ITKCommon_EXPORT MetaDataObject< long >;
template class ITKCommon_EXPORT MetaDataObject< float >;
template class ITKCommon_EXPORT MetaDataObject< double >;
template class ITKCommon_EXPORT MetaDataObject< std::string >;
template class ITKCommon_EXPORT MetaDataObject< Array<char> >;
template class ITKCommon_EXPORT MetaDataObject< Array<int> >;
template class ITKCommon_EXPORT MetaDataObject< Array<float> >;
template class ITKCommon_EXPORT MetaDataObject< Array<double> >;
template class ITKCommon_EXPORT MetaDataObject< Matrix<double> >;

} // end namespace itk

0 comments on commit b72726c

Please sign in to comment.