Example from and to python converters
Example code to illustrate how to use Boost.Python to wrap code, which uses VTK objects in the wrapped functions either as return value or as a function argument.
<source lang="cpp">
- include <boost/python.hpp>
- include <vtkPythonUtil.h>
- include <vtkUnstructuredGrid.h>
- include <vtkPoints.h>
- include <vtkActor.h>
- include <vtkPolyData.h>
using namespace boost::python;
// Useful discussion and descriptions:
//
// http://misspent.wordpress.com/2009/09/27/how-to-write-boost-python-converters/
// http://vtk.1045678.n5.nabble.com/Can-I-mix-Boost-Python-and-VTK-Python-wrapper-tt3396951.html#none
// http://visitusers.org/index.php?title=Python_Filters_Development
// http://docs.python.org/c-api/index.html
template<class T> struct vtkObjectPointer_to_python { static PyObject *convert(const T &p) { if(p == NULL) { return incref(Py_None); } std::ostringstream oss; oss << (vtkObjectBase*) p; // here don't get address std::string address_str = oss.str();
object obj = import("vtk").attr("vtkObjectBase")(address_str); return incref(obj.ptr()); } };
// // This python to C++ converter uses the fact that VTK Python objects have an // attribute called __this__, which is a string containing the memory address // of the VTK C++ object and its class name. // E.g. for a vtkPoints object __this__ might be "_0000000105a64420_p_vtkPoints" // // Alternative: use vtkPythonGetPointerFromObject from vtkPythonUtil.h void* extract_vtk_wrapped_pointer(PyObject* obj) {
char thisStr[] = "__this__"; //first we need to get the __this__ attribute from the Python Object if (!PyObject_HasAttrString(obj, thisStr)) return NULL;
PyObject* thisAttr = PyObject_GetAttrString(obj, thisStr); if (thisAttr == NULL) return NULL;
const char* str = PyString_AsString(thisAttr); if(str == 0 || strlen(str) < 1) return NULL;
char hex_address[32], *pEnd; char *_p_ = strstr(str, "_p_vtk"); if(_p_ == NULL) return NULL; char *class_name = strstr(_p_, "vtk"); if(class_name == NULL) return NULL; strcpy(hex_address, str+1); hex_address[_p_-str-1] = '\0';
long address = strtol(hex_address, &pEnd, 16);
vtkObjectBase* vtk_object = (vtkObjectBase*)((void*)address); if(vtk_object->IsA(class_name)) { return vtk_object; }
return NULL;
}
- define VTK_PYTHON_CONVERSION(type) \
/* register the to-python converter */ \ to_python_converter<type*, \ vtkObjectPointer_to_python<type*> >(); \ /* register the from-python converter */ \ converter::registry::insert(&extract_vtk_wrapped_pointer, type_id<type>());
//
// Example class to illustrate Boost Python wrapped class, which has
// functions which return VTK object pointers
//
struct MyClass
{
MyClass();
~MyClass();
void SetPoints(vtkPoints * pts);
vtkUnstructuredGrid * GetGrid() { return m_Grid; }
void DeleteGrid();
vtkUnstructuredGrid * m_Grid;
};
MyClass::MyClass() { m_Grid = vtkUnstructuredGrid::New();
m_Grid->Allocate(); vtkPoints *pts = vtkPoints::New(); pts->InsertNextPoint(0,0,0); pts->InsertNextPoint(1,0,0); m_Grid->SetPoints(pts); pts->Delete();
}
MyClass::~MyClass() { if(m_Grid) this->DeleteGrid(); }
void MyClass::DeleteGrid() { m_Grid->Delete(); m_Grid = NULL; }
void MyClass::SetPoints(vtkPoints *pts) {
m_Grid->SetPoints(pts);
}
//
// Create Python Module, with converters and MyClass wrapped
//
BOOST_PYTHON_MODULE(libBoostVTKConversion)
{
VTK_PYTHON_CONVERSION(vtkUnstructuredGrid);
VTK_PYTHON_CONVERSION(vtkPoints);
class_<MyClass>("MyClass") .def("GetGrid",&MyClass::GetGrid, return_value_policy<return_by_value>()) .def("DeleteGrid",&MyClass::DeleteGrid,"Delete the grid") .def("SetPoints",&MyClass::SetPoints,"Set new points") ; } </source>
<source lang="cmake"> PROJECT(BoostPythonVTK)
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
FIND_PACKAGE(VTK REQUIRED) INCLUDE(${VTK_USE_FILE}) SET(VTK_LIBS vtkGraphics vtkIO vtkCommon vtkImaging vtkFiltering vtkRendering)
FIND_PACKAGE(PythonLibs REQUIRED) MESSAGE(STATUS "PYTHON_LIBRARIES " ${PYTHON_LIBRARIES})
FIND_PACKAGE(Boost 1.45.0) IF(Boost_FOUND)
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIRS}) SET(Boost_USE_STATIC_LIBS OFF) SET(Boost_USE_MULTITHREADED ON) SET(Boost_USE_STATIC_RUNTIME OFF) FIND_PACKAGE(Boost 1.45.0 COMPONENTS python REQUIRED)
ADD_LIBRARY(BoostVTKConversion MODULE PythonModule_BoostVTKConversion.cxx vtkPythonUtil.cxx) TARGET_LINK_LIBRARIES(BoostVTKConversion ${Boost_LIBRARIES} ${PYTHON_LIBRARIES} ${VTK_LIBS})
ELSE()
MESSAGE(FATAL_ERROR "Unable to find correct Boost version. Did you set BOOST_ROOT?")
ENDIF() </source>