VTK/Wrapping hints

From KitwarePublic
< VTK
Revision as of 10:59, 25 January 2019 by Dgobbi (talk | contribs) (→‎vtk::nowrap)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigationJump to search

Sometimes the VTK wrappers need a little help in order to properly wrap certain C++ methods. Most often, this occurs when a method takes or returns a pointer. Some examples of the "unknowns" for a pointer that might have to be hinted are:

  • Does the API allow the pointer to be NULL?
  • Does it point to a single object, or an array?
  • If an array, what is the size of the array?
  • Will 'delete' or 'free()' have to be called to free the memory?
  • If the pointer is 'char *', is it null-terminated? Is it ASCII, utf-8, or latin1?

Hinting with attributes

C++11 introduced attributes to provide hints for the compiler, such as the [[noreturn]] attribute to indicate that a method will never return:

[[noreturn]] void exit(int status);

We are allowed to define our own attributes, as long as we define a unique namespace, e.g. [[vtk::name]]. However, we don't want the attributes to be be "naked" in the code, because that would break pre-C++11 compilers. Instead, we conditionally define the attributes within macros (this is done within vtkSetGet.h, as for most VTK macros).

 #ifdef __VTK_WRAP__
 #define VTK_NEWINSTANCE [[vtk::newinstance]]
 #else
 #define VTK_NEWINSTANCE
 #endif

Once this macro is defined, we can use it in our method declarations.

The only hint attributes that VTK provides right now are as follows:

[[vtk::newinstance]]

This indicates that the method returns a vtkObject that has just been created, and the caller must call Delete() on the returned value when done with it.

VTK_NEWINSTANCE
vtkObjectBase* NewInstance();

[[vtk::zerocopy]]

This indicates that a pointer parameter must be passed directly, without any copying of the data that it points to. For Python, it indicates that the "buffer" interface will be used for the parameter, rather than the "sequence" interface that is usually used for pointers and arrays.

void SetArray(VTK_ZEROCOPY float *buffer, vtkIdType size);

[[vtk::sizehint(expression)]]

[[vtk::sizehint(arg, expression)]]

These indicates that a pointer type, such as 'float *', points to an array of 'expression' values, where 'expression' is a C++ expression that evaluates to an integer.

// declare the size of the return value
double* GetPoint() VTK_SIZEHINT(3);

// a hint can be applied to any of the parameters (and multiple sizehints are allowed, too)
void InsertNextCell(vtkIdType n, vtkidType* ptIds) VTK_SIZEHINT(ptIds, n);

// "this" is understood to be a pointer to the object ("this->" can be omitted)
class vtkDataArray
{
  vtkIdType GetNumberOfComponents();

  void SetTuple(const double* tuple)
    VTK_SIZEHINT(tuple, this->GetNumberOfComponents());
}

[[vtk::expects(condition)]]

This indicates that 'condition' is a precondition for calling a method. If the condition is not met, then a ValueError exception is raised in Python and the C++ method is not called. Any number of 'expects' hints are allowed, they are checked in the order in which they appear.

class vtkDataArray
{
  vtkIdType GetNumberOfTuples();

  void SetTuple(i, const double* tuple)
    VTK_EXPECTS(i < GetNumberOfTuples())  // condition #1
    VTK_EXPECTS(tuple != nullptr); // condition #2
}

Proposed hints

These are hints that aren't supported by the wrappers yet, and might never be supported.

[[vtk::nevernull]]

This indicates that a pointer will never be null (if returned), or must never be null (if passed as a parameter).

void SetName(VTK_NEVERNULL const char *name);

[[vtk::unterminated]]

For "char *" or "const char *", this hint indicates that the string might not be terminated.

VTK_UNTERMINATED
const char* GetData();

[[vtk::takeref(method)]]

For a return value, this indicates that the caller should take ownership of the object and dispose of it by the given method, which can be "delete", "delete []", "free", etc. For a parameter, this indicates that the method will dispose of the object by the given method, and that the caller is no longer responsible for deletion.

VTK_TAKEREF(delete[])
char* CreateName();

[[vtk::wrapexclude]]

This hint indicates that a class or method should not be wrapped.