/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* ex: set filetype=cpp softtabstop=4 shiftwidth=4 tabstop=4 cindent expandtab: */ /* $Id: cmnClassRegisterMacros.h,v 1.5 2007/04/26 19:33:57 anton Exp $ Author(s): Anton Deguet Created on: 2006-10-30 (C) Copyright 2006-2007 Johns Hopkins University (JHU), All Rights Reserved. --- begin cisst license - do not edit --- This software is provided "as is" under an open source license, with no warranty. The complete license can be found in license.txt and http://www.cisst.org/cisst/license.txt. --- end cisst license --- */ /*! \file \brief Class registration macros. These macros can be divided in three sets, one of each should be used for any registered class. - #CMN_DECLARE_SERVICES and #CMN_DECLARE_SERVICES_EXPORT are used in the header file to add the declaration of methods and data members within the scope of the registered class. - #CMN_DECLARE_SERVICES_INSTANTIATION and #CMN_DECLARE_SERVICES_INSTANTIATION_EXPORT are used in the header file to declare a template specialization of the global function cmnClassServicesInstantiate for the registered class. - #CMN_IMPLEMENT_SERVICES and #CMN_IMPLEMENT_SERVICES_TEMPLATED are used in the source file to implement the methods declared by #CMN_DECLARE_SERVICES and the function specialization declared by #CMN_DECLARE_SERVICES_INSTANTIATION. The macros ending with _EXPORT are required to handle the generation of DLLs correctly with the different Microsoft compilers (see also #CISST_EXPORT) and the macro ending with _TEMPLATED is required to register a specialized version of a templated class. Finally, the definitions #CMN_DYNAMIC_CREATION and #CMN_NO_DYNAMIC_CREATION are provided to increase the code readability. */ /*! \name Methods declaration These macros are used to declare the required methods and data members for the class registration (see also cmnClassRegister). Every class which needs to be registered should include one of these macros within its declaration AND be derived from cmnGenericObject. To declare a registered class without dynamic creation, the header file myClass.h should have: \code class CISST_EXPORT myClass: public cmnGenericObject { CMN_DECLARE_SERVICES(#CMN_NO_DYNAMIC_CREATION, CMN_LOG_DEFAULT_LOD); public: ... }; \endcode The macro #CMN_DECLARE_SERVICES defines amongst other things a static method which can not be inlined. Therefore, when one wants to create a Dll (shared libraries on Windows) with a C++ compiler from Microsoft, one must explicitly export it. In most cases, the class itself is "exported" using #CISST_EXPORT. If the class is not wholly exported, it is possible to export some methods explicitly. In this case, the macro #CMN_DECLARE_SERVICES_EXPORT should be used: \code class myClass: public cmnGenericObject { CMN_DECLARE_SERVICES_EXPORT(CMN_NO_DYNAMIC_CREATION, CMN_LOG_DEFAULT_LOD); public: CISST_EXPORT void MethodA(void); ... }; \endcode \param hasDynamicCreation Set this parameter to #CMN_DYNAMIC_CREATION to enable dynamic creation and #CMN_NO_DYNAMIC_CREATION to disable dynamic creation. Dynamic creation requires a public default constructor. \param lod The default Level of Detail used for this class (see also #CMN_LOG and #CMN_LOG_DEFAULT_LOD. */ //@{ #ifdef CMN_DECLARE_SERVICES #undef CMN_DECLARE_SERVICES #endif #define CMN_DECLARE_SERVICES(hasDynamicCreation, lod) \ public: \ enum {HAS_DYNAMIC_CREATION = hasDynamicCreation}; \ enum {INITIAL_LOD = lod}; \ static cmnClassServicesBase * ClassServices(void); \ virtual cmnClassServicesBase * const Services(void) const \ { \ return this->ClassServices(); \ } \ private: \ static cmnClassServicesBase * ClassServicesPointer; #ifdef CMN_DECLARE_SERVICES_EXPORT #undef CMN_DECLARE_SERVICES_EXPORT #endif #define CMN_DECLARE_SERVICES_EXPORT(hasDynamicCreation, lod) \ public: \ enum {HAS_DYNAMIC_CREATION = hasDynamicCreation}; \ enum {INITIAL_LOD = lod}; \ CISST_EXPORT static cmnClassServicesBase * ClassServices(void); \ virtual cmnClassServicesBase * const Services(void) const \ { \ return this->ClassServices(); \ } \ private: \ static cmnClassServicesBase * ClassServicesPointer; //@} /*! \name Global function declaration The templated function cmnClassServicesInstantiate is used to generate a unique object of type cmnClassServices for each class defined in cisst. It contains a static data member which will be constructed the first time it is called. The header file myClass.h should have to following code after the class declaration of myClass: \code CMN_DECLARE_SERVICES_INSTANTIATION_EXPORT(myClass) \endcode In most case, #CMN_DECLARE_SERVICES_INSTANTIATION_EXPORT should be used. One case where #CMN_DECLARE_SERVICES_INSTANTIATION should be used in when the class instantiation will reside in the executable, i.e. the programmer is not creating a library but is linking all is binaries directly into and executable. For a template class, it is necessary to specify which template specialization is being registered. To do so, it is recommended to create a typedef before using this macro: \code template myClass<_templateParameter>: public cmnGenericObject { CMN_DECLARE_SERVICES_EXPORT(CMN_NO_DYNAMIC_CREATION, CMN_LOG_DEFAULT_LOD); public: ... }; typedef myClass myClassDouble; CMN_DECLARE_SERVICES_INSTANTIATION_EXPORT(myClassDouble) \endcode \param className The name of the class being registered, without any quote. */ //@{ #ifdef CMN_DECLARE_SERVICES_INSTANTIATION #undef CMN_DECLARE_SERVICES_INSTANTIATION #endif #define CMN_DECLARE_SERVICES_INSTANTIATION(className) \ template<> \ cmnClassServicesBase * cmnClassServicesInstantiate(void); #ifdef CMN_DECLARE_SERVICES_INSTANTIATION_EXPORT #undef CMN_DECLARE_SERVICES_INSTANTIATION_EXPORT #endif #define CMN_DECLARE_SERVICES_INSTANTIATION_EXPORT(className) \ template<> CISST_EXPORT \ cmnClassServicesBase * cmnClassServicesInstantiate(void); //@} /*! \name Methods and function implementation These macros implements the methods and function declared by #CMN_DECLARE_SERVICES and #CMN_DECLARE_SERVICES_INSTANTIATION_EXPORT. For a non templated class, the source file myClass.cpp must have: \code CMN_IMPLEMENT_SERVICES(myClass); \endcode For a templated class specialized and define using typedef ... myClassDouble, the source file must have: \code CMN_IMPLEMENT_SERVICES_TEMPLATED(myClassDouble); \endcode \param className The name of the class being registered, without any quote. */ //@{ #ifdef CMN_IMPLEMENT_SERVICES #undef CMN_IMPLEMENT_SERVICES #endif #define CMN_IMPLEMENT_SERVICES(className) \ cmnClassServicesBase * className::ClassServices(void) \ { \ static cmnClassServicesBase * classServices = cmnClassServicesInstantiate(); \ return classServices; \ } \ cmnClassServicesBase * className::ClassServicesPointer = className::ClassServices(); \ template<> \ cmnClassServicesBase * cmnClassServicesInstantiate(void) \ { \ static cmnClassServices classServices(#className, \ &typeid(className), \ className::INITIAL_LOD); \ return static_cast(&classServices); \ } #ifdef CMN_IMPLEMENT_SERVICES_TEMPLATED #undef CMN_IMPLEMENT_SERVICES_TEMPLATED #endif #define CMN_IMPLEMENT_SERVICES_TEMPLATED(className) \ template<> \ cmnClassServicesBase * className::ClassServices(void) \ { \ static cmnClassServicesBase * classServices = cmnClassServicesInstantiate(); \ return classServices; \ } \ template<> \ cmnClassServicesBase * className::ClassServicesPointer = className::ClassServices(); \ template<> \ cmnClassServicesBase * const className::Services(void) const \ { \ return this->ClassServices(); \ } \ template<> \ cmnClassServicesBase * cmnClassServicesInstantiate(void) \ { \ static cmnClassServices classServices(#className, \ &typeid(className), \ className::INITIAL_LOD); \ return static_cast(&classServices); \ } //@} /*! \name Possible values used in combination with #CMN_DECLARE_SERVICES and #CMN_DECLARE_SERVICES_EXPORT. */ //@{ /* This parameter allows to either register a class without dynamic creation (just for logging, usually a "processing" class) or register the class with dynamic creation (the log is still available, mostly for "data" objects). Dynamic creation can be used to create an object of a given type based on its name provided as a string. It is important to note that a class registered to allow dynamic creation must provide a default constructor. The C++ compiler will not be able to compile the code generated if the default constructor is missing. */ #ifdef CMN_DYNAMIC_CREATION #undef CMN_DYNAMIC_CREATION #endif #define CMN_DYNAMIC_CREATION true #ifdef CMN_NO_DYNAMIC_CREATION #undef CMN_NO_DYNAMIC_CREATION #endif #define CMN_NO_DYNAMIC_CREATION false //@} // **************************************************************************** // Change History // **************************************************************************** // // $Log: cmnClassRegisterMacros.h,v $ // Revision 1.5 2007/04/26 19:33:57 anton // All files in libraries: Applied new license text, separate copyright and // updated dates, added standard header where missing. // // Revision 1.4 2006/11/20 20:33:19 anton // Licensing: Applied new license to cisstCommon, cisstVector, cisstNumerical, // cisstInteractive, cisstImage and cisstOSAbstraction. // // Revision 1.3 2006/11/03 04:28:00 anton // cisstCommon: Major update of Doxygen documentation following changes re. // ticket #234. // // Revision 1.2 2006/10/31 20:33:34 anton // cmnClassRegisterMacros.h: Moved CMN_{NO_,}DYNAMIC_CREATION to this file // and removed macro CMN_DECLARE_SERVICES_INTERNAL since SWIG had some trouble // with the empty parameters (export being defined as CISST_EXPORT or nothing). // // Revision 1.1 2006/10/31 03:03:27 anton // cisstCommon: Place class registration macros in a new file to make sure they // are defined after CISST_EXPORT since they rely on CISST_EXPORT. Also added // macro CMN_DECLARE_SERVICES_INSTANTIATION_EXPORT to avoid warnings. Doxygen // documentation has to be updated (see ticket #234). // // // ****************************************************************************