Overview Writing Modules • Before You Start • Structure of a Module • Ports and Datatypes • Component Wizard • GUI’s • Dynamic Compilation NCRR Before You Start Design Your Function • • • • Writing Modules A Module is a Function Inputs and Outputs User Input (GUI Variables) Dataflow Coding Standard • Standards • Advice • SCIRun/doc/Developer/Guide/coding_standard.html NCRR Module Structure Writing Modules Support Files • • • • • • .cc file sub.mk .xml file .tcl file sub.mk .h file (optional) NCRR Ports and Datatypes Ports • • • • • Writing Modules LockingHandles Generation number Memory Management Sending Data Cache Results Datatypes • Fields, Matrix, SceneGraph • Detach (Dataflow) • Properties NCRR Component Wizard Adding a Module Writing Modules NCRR Component Wizard Writing Modules NCRR Component Wizard Edit a Port Writing Modules • Name • Namespace NCRR Component Wizard • Package • Category • Path Writing Modules NCRR Component Wizard • New Package? • New Category? • Reconfiguring. Writing Modules NCRR Component Wizard After Compiling Writing Modules NCRR Component Wizard Your Skeleton GUI Writing Modules NCRR GUI’s Writing Modules TCL • itcl • blt • Use Simple GUI as a Pattern • GuiVars NCRR GUI’s itcl_class SCIRun_Fields_SelectField { inherit Module constructor {config} { set name SelectField Writing Modules global $this-stampvalue global $this-runmode } set_defaults method set_defaults {} { set $this-stampvalue 100 set $this-runmode 0 # 0 nothing 1 accumulate 2 replace } method replace {} { set $this-runmode 2 $this-c needexecute } method accumulate {} { set $this-runmode 1 $this-c needexecute } NCRR GUI’s method ui {} { set w .ui[modname] if {[winfo exists $w]} { raise $w return } toplevel $w Writing Modules frame $w.row1 frame $w.row3 frame $w.row4 pack $w.row1 $w.row3 $w.row4 -side top -e y -f both -padx 5 -pady 5 label $w.row1.value_label -text "Selection Value" entry $w.row1.value -textvariable $this-stampvalue pack $w.row1.value_label $w.row1.value -side left button $w.row3.execute -text "Replace" -command "$this replace" pack $w.row3.execute -side top -e n -f both button $w.row4.execute -text "Accumulate" -command "$this accumulate" pack $w.row4.execute -side top -e n -f both } NCRR GUI’s Writing Modules GuiVars • Values to from C side - Initialize C++ side constructor synchs with tcl name tcl side sets the initial value - my_var.reset() - my_var.get() • tcl_command(...) - $this-c “needexecute” NCRR Dynamic Compilation Writing Modules Motivation • SCIRun::Field • Code Explosion • Extensibility • Maintenance NCRR Dynamic Compilation Writing Modules Field Types (4) TetVol, LatticeVol, ContourField, TriSurf Supported Data Types (9) double, int, char, unsigned char, short, unsigned short, bool, Vector, and Tensor An Algorithm Parameterized on One Field Type • Requires 36 Field instantiations • And 36 Algorithm Instantiations Parameterized On Two Fields • 362 = 1296 Versions of the Algorithm Parameterized On Three Fields • 363 = 46656 Versions of the Algorithm Actual implementation supports more Field and Data types Very few of these combinations are needed by any one person or application NCRR Algorithm Structure Writing Modules Algorithm Base Class • Inherits from common base class • Defines the pure virtual interface needed by a module • Provides a static CompileInfo Templated Algorithm • Implements the pure virtual interface in the base class • Potentially specialized for specific field type template<class Field> RenderField : public RenderFieldBase RenderFieldBase RenderField<TetVol<double> > virtual void render(FieldBase&)=0; RenderField<LatticeVol<double> > RenderField<TetVol<Vector> > RenderField<LatticeVol<Vector> > etc... NCRR TypeDescription TypeDescription object augments RTTI Holds: Writing Modules • Strings that describe object’s exact type • Namespace string • Path to the .h file that declares the object Has a recursive structure Example: foo<bar, foobar<int> >; foo bar foobar int NCRR CompileInfo Writing Modules Similar info as a TypeDescription Algorithm is not instantiated, so cannot yet be queried Start with a CompileInfo from Algorithm base class Augmented with information from all pertinent TypeDescription objects for the specific types involved Passed to DynamicLoader, which creates the proper type NCRR DynamicLoader Returns Requested Algorithm • • • • Writing Modules Writes C++ instantiation code Compile shared library, using SCIRun makefiles Load shared library (dlopen) Return Instance of Algorithm (Cached for next use) Synchronization code such that • Only 1 thread can compile at a time per algorithm • Multiple algorithms can compile and load at the same time NCRR Calling Module void ShowField::execute() { // Get a Field from input field port. field = (FieldIPort *)get_iport("Field"); field->get(field_handle); Writing Modules // Get the input field's type info. const TypeDescription *td = field_handle->get_type_description(); // Get the Algorithm. CompileInfo *ci = RenderFieldBase::get_compile_info(td); if (! DynamicLoader::scirun_loader().get(*ci, rend_algo)) { error("Could not compile algorithm for ShowField -"); return; } RenderFieldBase *rf = dynamic_cast<RenderFieldBase*>(rend_algo); // Let the templated algorithm render this field. rf->render(field_handle, /* any other parameters from gui */); } // Send results downstream... No template instantiations for the exact algorithm type NCRR Example Writing Modules //! ConvertTetBase supports the dynamically loadable algorithm concept. //! when dynamically loaded the user will dynamically cast to a //! ConvertTetBase from the DynamicAlgoBase they will have a pointer to. class ConvertTetBase : public DynamicAlgoBase { public: virtual FieldHandle convert_quadratic(FieldHandle in) = 0; virtual ~ConvertTetBase(); static const string& get_h_file_path(); static string dyn_file_name(const TypeDescription *td) { // add no extension. return template_class_name() + "." + td->get_filename() + "."; } static const string base_class_name() { static string name("ConvertTetBase"); return name; } static const string template_class_name() { static string name("ConvertTet"); return name; } //! support the dynamically compiled algorithm concept static CompileInfo *get_compile_info(const TypeDescription *td); }; NCRR Example Writing Modules template <class Fld> class ConvertTet : public ConvertTetBase { public: //! virtual interface. virtual FieldHandle convert_quadratic(FieldHandle in); }; template <class Fld> FieldHandle ConvertTet<Fld>::convert_quadratic(FieldHandle ifh) { Fld *fld = dynamic_cast<Fld*>(ifh.get_rep()); ASSERT(fld != 0); typedef typename Fld::value_type val_t; FieldHandle fh(QuadraticTetVolField<val_t>::create_from(*fld)); return fh; } NCRR Summary Writing Modules Concepts • Ports and Datatypes • Modules (Component Wizard) • Templated Algorithms • Dynamic Loading NCRR