Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members

cllite.h

00001 #ifndef cllite_CLLITE_H_INCLUDED
00002 #define cllite_CLLITE_H_INCLUDED 1
00003 
00004 ////////////////////////////////////////////////////////////////////////
00005 // cllite.h:
00006 // Defines a simplified front-end for the class_loader interfaces,
00007 // encapsulating the most-commonly-used classloading features.
00008 // It only supports string-keyed classloaders, and does not
00009 // support classloaders which serve shared instanced of objects.
00010 //
00011 // Author: stephan beal <stephan@s11n.net>
00012 // License: Public Domain
00013 ////////////////////////////////////////////////////////////////////////
00014 
00015 #include <string>
00016 
00017 #if HAVE_CONFIG_H
00018 #  include "config.h"
00019 #endif
00020 
00021 #include <s11n/class_loader.h> // core classloader framework.
00022 #include <s11n/cl_debuggering_macros.h> // CERR
00023 #include <s11n/path_finder.h> // path_finder class
00024 
00025 #define LITECERR if(s11n::class_loader_debug_level() > 0) CERR
00026 //#define LITECERR if(0) CERR
00027 
00028 #if ! WIN32
00029 #ifdef HAVE_LTDL // prefer libltdl, but if it's not available...
00030 #  include <ltdl.h>
00031 #else           // use libdl instead:
00032 #  include <dlfcn.h>
00033 #endif // HAVE_LTDL
00034 #else // WIN32:
00035 #  include <windows.h> // LoadModule(). All WIN32 code is 100% untested.
00036 #endif // !WIN32
00037 
00038 
00039 ////////////////////////////////////////////////////////////////////////////////
00040 // Shorthand forms of the usual class-to-loader registration macros,
00041 // for use by client code.
00042 // These are all documented at length in the lib manual and class_loader.h.
00043 #define CLLITE_BASE(BaseType) \
00044     s11n_CLASSLOADER_REGISTER1(BaseType)
00045 #define CLLITE_SUBTYPE(BaseType,SubType) \
00046     s11n_CLASSLOADER_REGISTER2(BaseType,SubType)
00047 #define CLLITE_ABSTRACT(BaseType) \
00048     s11n_CLASSLOADER_ABSTRACT_BASE(BaseType)
00049 ////////////////////////////////////////////////////////////////////////////////
00050 
00051 
00052 
00053 /**
00054    cllite is an experimental 'lite' front-end to the class_loader framework.
00055    It's intention is to provide the mostly-used class_loader<> functionality
00056    under one roof, and simplify it's interface.
00057 
00058    As of the introduction of cllite, the former dll_loader class is
00059    deprecated in favour of the functions in this namespace. The brief
00060    reason is that class_loader and dll_loader are not 100%
00061    usage-compatible, often causing some additional work in client
00062    code. The functions in this namespace provide more flexible DLL
00063    support than dll_loader without having to implement a class_loader
00064    subtype to do it. This code also demonstrates how class_loader can
00065    transparently work with arbitrary client-side DLL-opening code (reminder:
00066    class_loader requires NO special symbols in a DLL, as conventional
00067    classloaders do).
00068 */
00069 namespace cllite
00070 {
00071         /**
00072            The lookup key type used by classloaders in cllite.  Note
00073            that non-string types do not generically make sense in this
00074            context because DLL-awareness only works for strings. Why? 
00075            Consider: how do we load a DLL using an arbitrary
00076            non-string lookup key without imposing some type of
00077            translation conventions on clients?
00078         */
00079         typedef std::string key_type;
00080 
00081 
00082         /**
00083            Internal marker class for use with phoenix<>.
00084          */
00085         struct sharing_context;
00086 
00087 
00088         /**
00089            Returns this library's class search-path. It is up to specific
00090            classloaders to use or ignore this path: it is a
00091            suggestion, and not a rule. Clients are free to modify
00092            the returned object.
00093         */
00094         s11n::path_finder & class_path();
00095 
00096         /**
00097            A basic classname-to-DLL-name transformer.
00098 
00099            Intended to be used to transform namespaced/templated names
00100            into filename-friendly names.
00101 
00102 
00103         */
00104         struct classname_to_dllname
00105         {
00106                 typedef std::string key_type;
00107                 classname_to_dllname();
00108 
00109                 /**
00110                    ns_xlate sets the namespace separator (::) replacement which
00111                    will happen when this functor is activated. 
00112 
00113 
00114                    e.g., passing "/" will cause
00115                    foo::bar::MyType to translate to foo/bar/MyType
00116                 */
00117                 explicit classname_to_dllname( const key_type & ns_xlate );
00118 
00119                 /**
00120                    General conventions:
00121 
00122                    Should return a DLL-friendly name of the given key,
00123                    minus any extension: a set of platform-specific
00124                    extensions is sed by class_path(). See the
00125                    classname_to_dllname class for a sample
00126                    implementation.
00127 
00128                    This implementation transforms class names such
00129                    that:
00130 
00131                    - By default namespace separators (::)
00132                    are replaced by, "_", but this can be changed via the ctor
00133 
00134                    - Any template parameters are simply removed.
00135 
00136                    e.g.:
00137 
00138                    std::list<foo> = std_list
00139 
00140                    MyType = MyType
00141 
00142                    foo::bar::MyType = foo_bar_MyType
00143 
00144 
00145                 */
00146                 key_type operator()( const key_type & key ) const;
00147 
00148         private:
00149                 std::string m_nssep; // namespace separator replacement
00150         };
00151 
00152 
00153         /**
00154            Tries to open a DLL named basename, which should be
00155            either an absolute path/filename or a partial filename,
00156            without path and extension parts.
00157            
00158            class_path() will be used to resolve the full file name.
00159 
00160            Returns the path to the DLL, if one was found and opened,
00161            or an empty string on error.
00162 
00163            Reminder: the classloader architecture is such that simply
00164            opening a DLL is enough to trigger any classloader
00165            registrations which might live in it.
00166         */
00167         std::string open_dll( const std::string & basename );
00168 
00169         /**
00170            Returns open_dll( trans(key) ).
00171         */
00172         template <typename NameTransformer>
00173         std::string open_dll( const std::string & key,
00174                               const NameTransformer & trans )
00175         {
00176                 return open_dll( xlated, trans(key) );
00177         } // open_dll()
00178 
00179 
00180         /**
00181            Returns the same thing as the underlying dlerror()
00182            implementation. Just as dlerror() does, this
00183            function will return NULL if called twice in a
00184            row. That is, it's error code is only valid once,
00185            and then it will return NULL until another error
00186            happens.           
00187         */
00188         const char * dll_error();
00189 
00190 
00191 
00192         /**
00193            Returns the BaseType classloader, as selected by the
00194            classloader_selector&lt;BaseType&gt; class.
00195 
00196            Note that this object itself is not DLL-aware: use
00197            classload() to enable DLL lookups for missing classes.
00198         */
00199         template <typename BaseType>
00200         s11n::class_loader<BaseType> &
00201         classloader()
00202         {
00203                 return s11n::phoenix<
00204                         s11n::class_loader<BaseType>,
00205                         sharing_context >::instance();
00206         }
00207 
00208         /**
00209            Tries to load the class named 'key' from BaseType's classloader.
00210            If no such class is registered a DLL search is initiated to
00211            find the class, using a default classname-to-DLL-name translator.
00212 
00213            The caller owns the returned pointer, which may be 0
00214            (indicating the classloader could not find the DLL).
00215         */
00216         template <typename BaseType>
00217         BaseType * classload( const key_type & key )
00218         {
00219                 s11n::class_loader<BaseType> & cl =
00220                         classloader<BaseType>();
00221                 BaseType * ret = cl.load( key );
00222                 if( ret ) return ret;
00223                 LITECERR << "cllite looking for a DLL for '"<<key<<"'\n";
00224                 if( open_dll( classname_to_dllname()(key) ).empty() )
00225                 {
00226                         return 0;
00227                 }
00228                 return cl.load( key ); // try again!
00229         }
00230 
00231         /**
00232            Similar to classloader(), but the object it returns serves
00233            shared instances of objects.
00234         */
00235         template <typename BaseType>
00236         s11n::class_loader<BaseType,key_type,true> &
00237         classloader_shared()
00238         {
00239                 return s11n::phoenix<
00240                         s11n::class_loader<BaseType,key_type,true>,
00241                         sharing_context >::instance();
00242         }
00243 
00244 
00245         /**
00246            Similar to classload(), but objects returned by this function
00247            are NOT owned by the caller: the classloader cleans them up
00248            when it is destroyed (post-main()).
00249         */
00250         template <typename BaseType>
00251         BaseType * classload_shared( const key_type & key )
00252         {
00253                 typedef s11n::class_loader<BaseType,key_type,true> SharedCL;
00254                 SharedCL & cl = classloader_shared<BaseType>();
00255                 BaseType * ret = cl.load( key );
00256                 if( ret ) return ret;
00257                 LITECERR << "cllite looking for a DLL for '"<<key<<"'\n";
00258                 if( open_dll( classname_to_dllname()(key) ).empty() )
00259                 {
00260                         return 0;
00261                 }
00262                 return cl.load( key ); // try again!
00263         }
00264 
00265 
00266         /**
00267            Registers key with a factory returning (BaseType *).
00268         */
00269         template <typename BaseType>
00270         void register_factory( const key_type & key, BaseType * (*factory)() )
00271         {
00272                 classloader<BaseType>().register_factory( key, factory );
00273         }
00274 
00275         /**
00276            Registers a default factory for creating (SubType *) returned
00277            as (BaseType *).
00278          */
00279         template <typename BaseType, typename SubType>
00280         void register_factory( const key_type & key )
00281         {
00282                 register_factory<BaseType>( key,
00283                                             s11n::object_factory<BaseType,SubType>::new_instance
00284                                             );
00285         }
00286         
00287         /**
00288            Registers a default factory for BaseType.
00289         */
00290         template <typename BaseType>
00291         void register_base( const key_type & key )
00292         {
00293                 register_factory<BaseType,BaseType>( key );
00294         }
00295 
00296         /**
00297            Registers BaseType as an abstract base class. Use this for
00298            abstract base types, so that they get a working factory
00299            (i.e., one which always returns 0, since 'new BaseType'
00300            will not work for abstract types).
00301         */
00302         template <typename BaseType>
00303         void register_abstract_base( const key_type & key )
00304         {
00305                 register_factory( key,
00306                                   s11n::object_factory<BaseType>::no_instance
00307                                   );
00308         }
00309 
00310         /**
00311            Aliases thealias to be functionally equivalent to
00312            isthesameas for BaseType's classloader.
00313 
00314            This feature is useful for, e.g., assigning "friendly" or
00315            configurable names for a given application element. e.g.,
00316            consider the option of registering "DefaultDocumentClass"
00317            as an alias for some subtype of Document. This allows
00318            down-stream code to use symbolic names for loading
00319            application-specific types, as opposed to having to know
00320            the types real names.
00321         */
00322         template <typename BaseType>
00323         void alias( const key_type & thealias, const key_type & isthesameas )
00324         {
00325                 classloader<BaseType>().alias( thealias, isthesameas );
00326         }
00327 
00328 
00329 }
00330 
00331 #undef LITECERR
00332 #endif // cllite_CLLITE_H_INCLUDED

Generated on Tue Oct 26 18:25:59 2004 for s11n by  doxygen 1.3.9.1