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 Jul 20 10:46:47 2004 for s11n by doxygen 1.3.7