Example from and to python converters: Difference between revisions
(Added example code to mix VTK Python wrappers with Boost.Python wrapped code, which uses VTK objects) |
(Don't use vtkPythonUtil.h since it is VTK internal) |
||
Line 1: | Line 1: | ||
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. | 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. | ||
---- | ---- | ||
PythonModule_BoostVTKConversion.cxx: | |||
<source lang="cpp"> | <source lang="cpp"> | ||
#include <boost/python.hpp> | #include <boost/python.hpp> | ||
#include <vtkUnstructuredGrid.h> | #include <vtkUnstructuredGrid.h> | ||
#include <vtkPoints.h> | #include <vtkPoints.h> | ||
Line 47: | Line 47: | ||
// E.g. for a vtkPoints object __this__ might be "_0000000105a64420_p_vtkPoints" | // E.g. for a vtkPoints object __this__ might be "_0000000105a64420_p_vtkPoints" | ||
// | // | ||
void* extract_vtk_wrapped_pointer(PyObject* obj) | void* extract_vtk_wrapped_pointer(PyObject* obj) | ||
{ | { | ||
Line 153: | Line 152: | ||
---- | ---- | ||
CMakeLists.txt: | |||
<source lang="cmake"> | <source lang="cmake"> | ||
Line 161: | Line 162: | ||
FIND_PACKAGE(VTK REQUIRED) | FIND_PACKAGE(VTK REQUIRED) | ||
INCLUDE(${VTK_USE_FILE}) | INCLUDE(${VTK_USE_FILE}) | ||
SET(VTK_LIBS vtkGraphics vtkIO vtkCommon vtkImaging vtkFiltering | SET(VTK_LIBS vtkGraphics vtkIO vtkCommon vtkImaging vtkFiltering) | ||
FIND_PACKAGE(PythonLibs REQUIRED) | FIND_PACKAGE(PythonLibs REQUIRED) | ||
Line 174: | Line 175: | ||
FIND_PACKAGE(Boost 1.45.0 COMPONENTS python REQUIRED) | FIND_PACKAGE(Boost 1.45.0 COMPONENTS python REQUIRED) | ||
ADD_LIBRARY(BoostVTKConversion MODULE PythonModule_BoostVTKConversion | ADD_LIBRARY(BoostVTKConversion MODULE PythonModule_BoostVTKConversion.cxx) | ||
TARGET_LINK_LIBRARIES(BoostVTKConversion ${Boost_LIBRARIES} ${PYTHON_LIBRARIES} ${VTK_LIBS}) | TARGET_LINK_LIBRARIES(BoostVTKConversion ${Boost_LIBRARIES} ${PYTHON_LIBRARIES} ${VTK_LIBS}) | ||
Revision as of 17:58, 13 June 2011
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.
PythonModule_BoostVTKConversion.cxx:
<source lang="cpp">
- include <boost/python.hpp>
- include <vtkUnstructuredGrid.h>
- include <vtkPoints.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" // 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>
CMakeLists.txt:
<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)
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) 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>