00001 /*!@file Component/ComponentFactory.H Factory to create ModelComponent objects from a key string */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00005 // by the University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: Rob Peters <rjpeters at usc dot edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Component/ComponentFactory.H $ 00035 // $Id: ComponentFactory.H 8274 2007-04-19 17:44:48Z rjpeters $ 00036 // 00037 00038 #ifndef COMPONENT_COMPONENTFACTORY_H_DEFINED 00039 #define COMPONENT_COMPONENTFACTORY_H_DEFINED 00040 00041 #include "nub/ref.h" 00042 #include "rutz/factory.h" 00043 00044 class OptionManager; 00045 00046 /// Factory to create ModelComponent-derivative objects from a key string. 00047 /** The template class P should be some class that is derived from 00048 ModelComponent, and that is also the root of some sub-tree of the 00049 full inheritance graph. 00050 00051 Here's a quick overview of how ComponentFactory can be used with 00052 plugins and dynamic loading. You would use this system when you 00053 have multiple concrete classes derived from a base class, and you 00054 want to be able to select a particular concrete type to use at run 00055 time, based on some user input (e.g. a string passed to a 00056 command-line option). First, you create a ComponentFactory that is 00057 going to build products derived from a different type. Then, you 00058 install a PluginFallback for that factory that tells it "if you 00059 don't already know about the type, then first try to load an 00060 appropriately-named plugin module, and then try again to see if 00061 that plugin has now informed you about the type". 00062 00063 For an example of all this, see Media/FrameSeries.C, where we use 00064 the factories defined in Transport/FrameIstreamFactory.H. We 00065 populate the factories with some statically-known types, and then 00066 we install a PluginFallback. The PluginFallback essentially says, 00067 if we get --in=foobar on the command line, and our factory doesn't 00068 know anything about 'foobar' yet, then it should look for a plugin 00069 library named <plugins>/FrameIstream/foobar.so, and it should try 00070 to find an init function named frameistream_foobar_init() in that 00071 library. Presumably, that function frameistream_foobar_init() will 00072 then tell the factory how to make a 'foobar', and so when the 00073 PluginFallback returns, the factory can try again to make a 00074 'foobar'. 00075 00076 To actually try out a plugin, try the following: 00077 \verbatim 00078 make bin/ezvision 00079 make plugins 00080 ./bin/ezvision --in=tests/inputs/mpegclip1.mpg -T --out=display --out=debug 00081 \endverbatim 00082 00083 and within the log output you will see something like this: 00084 \verbatim 00085 Plugin::loadPlugin: opening /lab/rjpeters/projects/saliency/lib/invt/plugins/FrameOstream/debug.so 00086 Plugin::loadPlugin: running frameostream_debug_init() from /lab/rjpeters/projects/saliency/lib/invt/plugins/FrameOstream/debug.so 00087 debug::frameostream_debug_init: Hello from frameostream_debug_init()! 00088 \endverbatim 00089 00090 and then you will start seeing output from the DebugOstream that 00091 is built by --out=debug. 00092 */ 00093 template <class P> 00094 class ComponentFactory : public rutz::factory<nub::ref<P> > 00095 { 00096 public: 00097 typedef nub::ref<P> ProductType; 00098 00099 ComponentFactory(const char* keydescr, bool nocase = false) 00100 : 00101 rutz::factory<nub::ref<P> >(keydescr, nocase) 00102 {} 00103 00104 template <class T> 00105 void registerType(const char* name, OptionManager& mgr) 00106 { 00107 this->register_creator(new ComponentCreator<T>(mgr), name); 00108 } 00109 00110 nub::ref<P> createObj(const char* type) const 00111 { 00112 return this->new_checked_object(rutz::fstring(type)); 00113 } 00114 00115 private: 00116 /// Creator class that creates ModelComponent derivatives on demand. 00117 /** The only trick here is that we have to store a reference to an 00118 OptionManager, since (by convention) all ModelComponent classes 00119 take an OptionManager as the first arg to their constructor. */ 00120 template <class T> 00121 class ComponentCreator : public rutz::creator_base<nub::ref<P> > 00122 { 00123 public: 00124 ComponentCreator(OptionManager& mgr) 00125 : itsManager(mgr) {} 00126 00127 ComponentCreator(const ComponentCreator& that) 00128 : rutz::creator_base<nub::ref<P> >(that), 00129 itsManager(that.itsManager) {} 00130 00131 virtual ~ComponentCreator() {} 00132 00133 virtual rutz::creator_base<nub::ref<P> >* clone() const 00134 { return new ComponentCreator(*this); } 00135 00136 virtual nub::ref<P> create() 00137 { return nub::ref<P>(new T(itsManager)); } 00138 00139 private: 00140 OptionManager& itsManager; 00141 }; 00142 }; 00143 00144 // ###################################################################### 00145 /* So things look consistent in everyone's emacs... */ 00146 /* Local Variables: */ 00147 /* mode: c++ */ 00148 /* indent-tabs-mode: nil */ 00149 /* End: */ 00150 00151 #endif // COMPONENT_COMPONENTFACTORY_H_DEFINED