VTK/Wrapping hints: Difference between revisions

From KitwarePublic
< VTK
Jump to navigationJump to search
 
(11 intermediate revisions by the same user not shown)
Line 25: Line 25:
Once this macro is defined, we can use it in our method declarations.
Once this macro is defined, we can use it in our method declarations.


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


===[[<nowiki />vtk::newinstance]]===
===[[<nowiki />vtk::newinstance]]===
Line 34: Line 34:
VTK_NEWINSTANCE
VTK_NEWINSTANCE
vtkObjectBase* NewInstance();
vtkObjectBase* NewInstance();
</pre>
===[[<nowiki />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.
<pre>
void SetArray(VTK_ZEROCOPY float *buffer, vtkIdType size);
</pre>
</pre>


===[[<nowiki />vtk::sizehint(expression)]]===
===[[<nowiki />vtk::sizehint(expression)]]===
===[[<nowiki />vtk::sizehint(arg, 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.
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.


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


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


// "this" is understood to be a pointer to the object
// "this" is understood to be a pointer to the object ("this->" can be omitted)
#define VTK_TUPLESIZE VTK_SIZEHINT(this->GetNumberOfComponents())
class vtkDataArray
class vtkDataArray
{
{
   VTK_TUPLESIZE double* GetTuple();
   vtkIdType GetNumberOfComponents();
   void SetTuple(VTK_TUPLESIZE const double* tuple)
 
   void SetTuple(const double* tuple)
    VTK_SIZEHINT(tuple, this->GetNumberOfComponents());
}
}
</pre>
</pre>
===[[<nowiki />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.
<pre>
class vtkDataArray
{
  vtkIdType GetNumberOfTuples();
  void SetTuple(i, const double* tuple)
    VTK_EXPECTS(i < GetNumberOfTuples())  // condition #1
    VTK_EXPECTS(tuple != nullptr); // condition #2
}
</pre>
==Proposed hints==
These are hints that aren't supported by the wrappers yet, and might never be supported.


===[[<nowiki />vtk::nevernull]]===
===[[<nowiki />vtk::nevernull]]===
Line 66: Line 95:
===[[<nowiki />vtk::unterminated]]===
===[[<nowiki />vtk::unterminated]]===


For "char *" or "const char *", this hint indicates that the string might not be terminated.  Similarly, [[<nowiki />vtk::terminated]] indicates that the string is definitely terminated.
For "char *" or "const char *", this hint indicates that the string might not be terminated.


<pre>
<pre>
Line 81: Line 110:
char* CreateName();
char* CreateName();
</pre>
</pre>
===[[<nowiki />vtk::wrapexclude]]===
This hint indicates that a class or method should not be wrapped.

Latest revision as of 15:59, 25 January 2019

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.