VTK/Wrapping hints

From KitwarePublic
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);

There are several hint attributes that could be added in the future:

[[vtk::sizehint(expression)]]

This 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.

VTK_SIZEHINT(3)
double* GetPoint();

// the function's parameters can be used in the hint expression
void InsertNextCell(vtkIdType n, VTK_SIZEHINT(n) vtkidType* ptIds);

// "this" is understood to be a pointer to the object
#define VTK_TUPLESIZE VTK_SIZEHINT(this->GetNumberOfComponents())
class vtkDataArray
{
  vtkIdType GetNumberOfComponents();
  VTK_TUPLESIZE double* GetTuple();
  void SetTuple(VTK_TUPLESIZE const double* tuple)
}

[[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::nowrap]]

This hint indicates that a method should not be wrapped.