VTK/WrapHierarchy: Difference between revisions

From KitwarePublic
< VTK
Jump to navigationJump to search
 
(44 intermediate revisions by the same user not shown)
Line 1: Line 1:
WrapHierarchy is a proposed tool for generating a text file (or multiple files) that describe the VTK class hierarchy.  The goal is to make the full VTK class hierarchy available to the wrappers at compile time, so that they can do special wrapping of classes depending on their superclasses (or absence of superclasses), even if the superclass in question is several generations from the class that is being wrapped.
WrapHierarchy is a tool for generating a text file (or multiple files) that describe the VTK class hierarchy.  The goal is to make the full VTK class hierarchy available to the wrapper-generators while they are generating the wrapper code.


==Why is this tool useful?==
==Why is this tool useful?==


* vtkObjectBase-derived parameters and parameters of vtk "special" types can be handled differently  
It will allow the wrappers to do type checking at code-generation time.
* certain categories of classes, e.g. array classes, can be given specific features
* all typedefs can be resolved to their native type
* any class can be type-checked (e.g. classes that are used as args and return values)
* vtkObjectBase-derived classes and vtk "special" types like vtkVariant can be handled differently  
* certain VTK sub-hierarchies, e.g. vtkDataArray's descendants , can be given specific features
* types that are external to the kit being wrapped can be detected, since they will be absent from the hierarchy


==File Format==
==File Format==


The hierarchy file will have the following format:
The hierarchy file will have a simple format that provides the class name, superclasses, header file, and cmake flags for each VTK class:


   vtkObjectBase ; vtkObjectBase.h
   vtkObjectBase ; vtkObjectBase.h
   vtkObject : vtkObjectBase ; vtkObject.h
   vtkObject : vtkObjectBase ; vtkObject.h
   vtkSimpleMutexLock ; vtkMutexLock.h
   vtkSimpleMutexLock ; vtkMutexLock.h ; WRAP_EXCLUDE
   vtkMutexLock : vtkObject ; vtkMutexLock.h
   vtkMutexLock : vtkObject ; vtkMutexLock.h
   vtkVariant ; vtkVariant.h
   vtkVariant ; vtkVariant.h ; WRAP_EXCLUDE ; WRAP_SPECIAL


There may be some classes that are sublassed from STL classes or other third-party classes.  There is no problem with this, the superclass will still be listed but the hierarchy above that point will not be available in the file.  In the case of multiple inheritance (which will hopefully be very rare) there will be entries like this:
There may be some classes that are subclassed from STL classes or other third-party classes.  There is no problem with this, the superclass will still be listed but the hierarchy above that point will not be available.  In the case of multiple inheritance (which will hopefully be very rare) there will be entries like this:


   vtkCrazyClass : vtkObjectBase , boof::baz ; vtkMisnamedHeader.h
   vtkCrazyClass : vtkObjectBase , std::vector<double> ; vtkSomeHeader.h
 
Typedefs are uncommon in VTK, but are still present.  They must also be included in the file:
 
vtkCollectionSimpleIterator = * void ; vtkCollection.h
 
An indirection for the type is listed in the following order: arrays, then pointers (in reverse order as compared to C declarations), then "const", then the original type.  For example:
 
vtkSomeType = [2][3]const** const int ; (equivalent to typedef const int **const[2][3];)
 
The idea is to list the indirection in order starting at the typedef name, and progressing to the original type, in a manner that eliminates any need for parentheses.


==How can this be done?==
==How can this be done?==


Three pieces are needed:
Three pieces are needed:
* a vtkWrapHierarchy executable to read header files and output all classes, superclasses for the file
* a vtkWrapHierarchy executable to read header files and output the names of all classes with their superclasses
* a CMake macro to call vtkWrapHierarchy on all VTK classes
* a CMake macro to call vtkWrapHierarchy on each kit, and to provide a .data file that lists all header files to be read
* a utility function to read hierarchy files so that the wrappers can use them
* a utility function to read the hierarchy files so that the Python, Java, and Tcl wrappers can use them


A big issue is how to handle dependencies.  Having one big hierarchy file could be a problem because a change to any VTK header file would mean that all the wrappers would have to be regenerated.  Having a small stub hierarchy file for each class header file means that the wrappers would have to read many small files.  A good solution might be to have CMake generate a "temporary" hierarchy file, compare it to the existing file (if one exists), and only replace the existing file if the new file is different.  That way, the wrappers will only have to be completely re-generated if the hierarchy changes.
A big issue is how to handle dependencies.  Having one big hierarchy file could be a problem because a change to any VTK header file would mean that all the wrappers would have to be regenerated.  Having a small stub hierarchy file for each class header file means that the wrappers would have to read many small files.  A good solution might be to have CMake generate a "temporary" hierarchy file, compare it to the existing file (if one exists), and only replace the existing file if the new file is different.  That way, the wrappers will only have to be completely re-generated if the hierarchy changes.


If this is done, then there can be one "hierarchy" file per kit.  Even better, the hierarchy file for each kit can be a merger of the kit's classes those of all the dependency kits.  That way, the wrappers only have to take in a single file, more-or-less a second "hints" file of sorts called "hierarchy".
The goal is to have one "hierarchy" file per kit.  Ideally, the hierarchy file for each kit can be a merger of that kit's classes those of all the dependency kits, i.e. the Filtering hierarchy file will include all classes defined in CommonIf this is done, the wrappers will only have to take in a single hierarchy file, which will more-or-less be a second "hints" file called "hierarchy".  Unlike "hints", the hierarchy file will be automatically generated.


==Difficulties==
==Difficulties==
Line 38: Line 52:
# the "hierarchy" file will depend on all header files in the kit, and on the "hierarchy" files for all dependency kits
# the "hierarchy" file will depend on all header files in the kit, and on the "hierarchy" files for all dependency kits


However, we don't want the kit wrappers to depend on all header files.  There has to be a break of sorts between 1) and 2), so that the dependency 1) is only triggered if dependency 2) resulted in changes to the hierarchy file.
However, we don't want the kit wrappers to depend on all kit header files, because this would lead to a lot of unnecessary recompiling.  There has to be a break of sorts between 1) and 2), so that the dependency 1) is only triggered if dependency 2) resulted in changes to the hierarchy file.


===Issue 2===
===Issue 2===
Merging the hierarchy files.  Can CMake do this, or will a separate utility executable be required?  The files just have to be concatenated, and then all duplicates have to be removed.
Merging the hierarchy files, i.e. so that Filtering contains all entries from Common.  Can CMake do this, or will a separate utility executable be required?  The files just have to be concatenated, and then all duplicates have to be removed.  The best thing is for the vtkWrapHierarchy executable to do the merging, since it can simply take all the files to be merged as command-line arguments.


==The Plan==
==The Plan==


The generation of the hierarchy files can be done according to the following scheme:
The generation of the hierarchy files can be done according to the following scheme:
# CMake generates a vtkKitHierarchy.data file with all the class names in the kit  
# CMake generates a vtkKitHierarchy.data file that lists all the header files to be wrapped for the kit  
# vtkWrapHierarchy generates a tiny stub .hfc file for each class header file (depends only on the header file)
# vtkWrapHierarchy generates hierarchy info by parsing all header files in vtkKitHierarchy.data
# vtkBuildHierarchy takes vtkKitHierachy.data (and the files from kit dependencies) and makes a temporary concatenation of all .hfc files
# vtkWrapHierarchy will also read the hierachy files from kits listed as its dependencies, e.g. Filtering will include Common
# vtkBuildHierarchy checks against the existing vtkKitHierarchy.txt file, replaces it if necessary
# vtkWrapHierarchy checks for a pre-existing vtkKitHierarchy.txt output file, replaces it only if the hierarchy has changed
# wrappers that need hierarchy info depend on the vtkKitHeirarchy file, and take it as a --heirarchy argument.
# any wrappers commands that need hierarchy info depend on the vtkKitHeirarchy file, and take it as a --heirarchy argument.


Notes:
Notes:
* vtkWrapHierarchy will be just like vtkWrapPython or the other wrapper generators
* vtkWrapHierarchy will be like vtkWrapPython et al. except that it will read several headers and produce just a single file per kit
* vtkBuildHeirarchy will be a custom executable that can read the stubs, weed out duplicates, read the output file, and only write the output file if it will change
* vtkWrapHierarchy will only write a new output file if the hierarchy has changed (it pre-reads the output file in order to check this)
* vtkParse.y will have code for reading the hierarchy file if given a --heirarchy option
* vtkParseHierarchy.c will be a module that can be linked to wrapper-generators, it will have code for reading the hierarchy file
* vtkParse.y will have a new --hierarchy option so that the hierarchy file can be given on the command-line
 
==The Execution==
 
The tools described above are now part of VTK and [http://github.com/dgobbi/WrapVTK WrapVTK].  Here are the features:
* the hierarchy file for each kit includes all classes of dependency kits, i.e. Filtering also includes Common classes
* the hierarchy file is only re-written when the hierarchy changes, which eliminates needless re-builds of the wrappers
* vtkParseHierarchy has the following methods to allow the wrappers to use the hierarchy files:
** HierarchyInfo *'''vtkParseHierarchy_ReadFile'''(const char *filename); // read a hierarchy file and return a data structure
** void '''vtkParseHierarchy_Free'''(HierarchyInfo *info); // free a hierarchy data structure
** int '''vtkParseHierarchy_IsExtern'''(HierarchyInfo *info, const char *classname); // check if a class is not in the hierarchy
** int '''vtkParseHierarchy_IsTypeOf'''(HierarchyInfo *info, const char *subclass, const char *superclass);
** int '''vtkParseHierarchy_CheckProperty'''(HierarchyInfo *info, const char *classname, const char *property);
** const char *'''vtkParseHierarchy_ClassHeader'''(HierarchyInfo *info, const char *classname);
** const char *'''vtkParseHierarchy_ClassSuperClass'''(HierarchyInfo *info, const char *classname, int idx);
** int '''vtkParseHierarchy_IsTypedef('''HierarchyInfo *info, const char *classname);
** const char *'''vtkParseHierarchy_GetRealType('''HierarchyInfo *info, const char *classname);

Latest revision as of 16:39, 13 October 2010

WrapHierarchy is a tool for generating a text file (or multiple files) that describe the VTK class hierarchy. The goal is to make the full VTK class hierarchy available to the wrapper-generators while they are generating the wrapper code.

Why is this tool useful?

It will allow the wrappers to do type checking at code-generation time.

  • all typedefs can be resolved to their native type
  • any class can be type-checked (e.g. classes that are used as args and return values)
  • vtkObjectBase-derived classes and vtk "special" types like vtkVariant can be handled differently
  • certain VTK sub-hierarchies, e.g. vtkDataArray's descendants , can be given specific features
  • types that are external to the kit being wrapped can be detected, since they will be absent from the hierarchy

File Format

The hierarchy file will have a simple format that provides the class name, superclasses, header file, and cmake flags for each VTK class:

 vtkObjectBase ; vtkObjectBase.h
 vtkObject : vtkObjectBase ; vtkObject.h
 vtkSimpleMutexLock ; vtkMutexLock.h ; WRAP_EXCLUDE
 vtkMutexLock : vtkObject ; vtkMutexLock.h
 vtkVariant ; vtkVariant.h ; WRAP_EXCLUDE ; WRAP_SPECIAL

There may be some classes that are subclassed from STL classes or other third-party classes. There is no problem with this, the superclass will still be listed but the hierarchy above that point will not be available. In the case of multiple inheritance (which will hopefully be very rare) there will be entries like this:

 vtkCrazyClass : vtkObjectBase , std::vector<double> ; vtkSomeHeader.h

Typedefs are uncommon in VTK, but are still present. They must also be included in the file:

vtkCollectionSimpleIterator = * void ; vtkCollection.h

An indirection for the type is listed in the following order: arrays, then pointers (in reverse order as compared to C declarations), then "const", then the original type. For example:

vtkSomeType = [2][3]const** const int ; (equivalent to typedef const int **const[2][3];)

The idea is to list the indirection in order starting at the typedef name, and progressing to the original type, in a manner that eliminates any need for parentheses.

How can this be done?

Three pieces are needed:

  • a vtkWrapHierarchy executable to read header files and output the names of all classes with their superclasses
  • a CMake macro to call vtkWrapHierarchy on each kit, and to provide a .data file that lists all header files to be read
  • a utility function to read the hierarchy files so that the Python, Java, and Tcl wrappers can use them

A big issue is how to handle dependencies. Having one big hierarchy file could be a problem because a change to any VTK header file would mean that all the wrappers would have to be regenerated. Having a small stub hierarchy file for each class header file means that the wrappers would have to read many small files. A good solution might be to have CMake generate a "temporary" hierarchy file, compare it to the existing file (if one exists), and only replace the existing file if the new file is different. That way, the wrappers will only have to be completely re-generated if the hierarchy changes.

The goal is to have one "hierarchy" file per kit. Ideally, the hierarchy file for each kit can be a merger of that kit's classes those of all the dependency kits, i.e. the Filtering hierarchy file will include all classes defined in Common. If this is done, the wrappers will only have to take in a single hierarchy file, which will more-or-less be a second "hints" file called "hierarchy". Unlike "hints", the hierarchy file will be automatically generated.

Difficulties

Issue 1

Assuming that everything is done according to the scheme outlined above, then some fancy CMake work is needed:

  1. the kit wrappers will depend on the "hierarchy" file for the kit
  2. the "hierarchy" file will depend on all header files in the kit, and on the "hierarchy" files for all dependency kits

However, we don't want the kit wrappers to depend on all kit header files, because this would lead to a lot of unnecessary recompiling. There has to be a break of sorts between 1) and 2), so that the dependency 1) is only triggered if dependency 2) resulted in changes to the hierarchy file.

Issue 2

Merging the hierarchy files, i.e. so that Filtering contains all entries from Common. Can CMake do this, or will a separate utility executable be required? The files just have to be concatenated, and then all duplicates have to be removed. The best thing is for the vtkWrapHierarchy executable to do the merging, since it can simply take all the files to be merged as command-line arguments.

The Plan

The generation of the hierarchy files can be done according to the following scheme:

  1. CMake generates a vtkKitHierarchy.data file that lists all the header files to be wrapped for the kit
  2. vtkWrapHierarchy generates hierarchy info by parsing all header files in vtkKitHierarchy.data
  3. vtkWrapHierarchy will also read the hierachy files from kits listed as its dependencies, e.g. Filtering will include Common
  4. vtkWrapHierarchy checks for a pre-existing vtkKitHierarchy.txt output file, replaces it only if the hierarchy has changed
  5. any wrappers commands that need hierarchy info depend on the vtkKitHeirarchy file, and take it as a --heirarchy argument.

Notes:

  • vtkWrapHierarchy will be like vtkWrapPython et al. except that it will read several headers and produce just a single file per kit
  • vtkWrapHierarchy will only write a new output file if the hierarchy has changed (it pre-reads the output file in order to check this)
  • vtkParseHierarchy.c will be a module that can be linked to wrapper-generators, it will have code for reading the hierarchy file
  • vtkParse.y will have a new --hierarchy option so that the hierarchy file can be given on the command-line

The Execution

The tools described above are now part of VTK and WrapVTK. Here are the features:

  • the hierarchy file for each kit includes all classes of dependency kits, i.e. Filtering also includes Common classes
  • the hierarchy file is only re-written when the hierarchy changes, which eliminates needless re-builds of the wrappers
  • vtkParseHierarchy has the following methods to allow the wrappers to use the hierarchy files:
    • HierarchyInfo *vtkParseHierarchy_ReadFile(const char *filename); // read a hierarchy file and return a data structure
    • void vtkParseHierarchy_Free(HierarchyInfo *info); // free a hierarchy data structure
    • int vtkParseHierarchy_IsExtern(HierarchyInfo *info, const char *classname); // check if a class is not in the hierarchy
    • int vtkParseHierarchy_IsTypeOf(HierarchyInfo *info, const char *subclass, const char *superclass);
    • int vtkParseHierarchy_CheckProperty(HierarchyInfo *info, const char *classname, const char *property);
    • const char *vtkParseHierarchy_ClassHeader(HierarchyInfo *info, const char *classname);
    • const char *vtkParseHierarchy_ClassSuperClass(HierarchyInfo *info, const char *classname, int idx);
    • int vtkParseHierarchy_IsTypedef(HierarchyInfo *info, const char *classname);
    • const char *vtkParseHierarchy_GetRealType(HierarchyInfo *info, const char *classname);