Example from and to python converters: Difference between revisions

From KitwarePublic
Jump to navigationJump to search
(Added example code to mix VTK Python wrappers with Boost.Python wrapped code, which uses VTK objects)
 
(Added useful URLs)
 
(One intermediate revision by the same user not shown)
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.
Useful discussions and descriptions:
* [http://misspent.wordpress.com/2009/09/27/how-to-write-boost-python-converters/ How to write boost converters]
* [http://vtk.1045678.n5.nabble.com/Can-I-mix-Boost-Python-and-VTK-Python-wrapper-tt3396951.html#none vtkusers: Can I mix Boost-Python and VTK-Python]
* [http://visitusers.org/index.php?title=Python_Filters_Development Use of VTK in Visit project]
* [http://docs.python.org/c-api/index.html Python C-API]
* [http://vtk.1045678.n5.nabble.com/Mixing-Boost-Python-and-VTK-Python-tt4428121.html vtkusers: Mails leading to this page]


----
----
PythonModule_BoostVTKConversion.cxx:


<source lang="cpp">
<source lang="cpp">
#include <boost/python.hpp>
#include <boost/python.hpp>


#include <vtkPythonUtil.h>
#include <vtkUnstructuredGrid.h>
#include <vtkUnstructuredGrid.h>
#include <vtkPoints.h>
#include <vtkPoints.h>
#include <vtkActor.h>
#include <vtkPolyData.h>




using namespace boost::python;
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>
template<class T>
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"
//
//
// Alternative: use vtkPythonGetPointerFromObject from vtkPythonUtil.h
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 vtkRendering)
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.cxx vtkPythonUtil.cxx)
   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})



Latest revision as of 18:05, 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.

Useful discussions and descriptions:

* How to write boost converters
* vtkusers: Can I mix Boost-Python and VTK-Python
* Use of VTK in Visit project
* Python C-API
* vtkusers: Mails leading to this page

PythonModule_BoostVTKConversion.cxx:

<source lang="cpp">

  1. include <boost/python.hpp>
  1. include <vtkUnstructuredGrid.h>
  2. include <vtkPoints.h>


using namespace boost::python;


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;

}


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