To wrap a C++ object with a known address into python, in the past, we have used something like the following:
vtkobj = vtk.vtkDataSet('01e3456')
The string arg holds the hex address of an existing C++ vtkDataSet pointer w/o the 0x prefix.
This isn’t working for me with VTK 9.4 or 9.5.
Working through docs and examples - I see a few more patterns floating around:
Init with string that includes 0x prefix:
vtkobj = vtk.vtkDataSet('0x01e3456')
And two more that I have pieced together that use more descriptive strings:
vtkobj = vtk.vtkDataSet('_01e3456_p_vtkDataSet')
vtkobj = vtk.vtkDataSet('_01e3456_vtkDataSet_p')
And there are some that have padded zeros at the start of the string.
What is the proper way?
In all cases, I am seeing a puzzling constructor error:
<class 'TypeError'>__init__() takes 1 positional argument but 2 were given
I am very confused by this message, as I am only passing a single string arg. I worry it’s internal to the wrapping. If I remove the string argument completely and try to default construct a vtkDataSet I get an expected error about vtkDataSet being a virtual base case that can’t be constructed. That test rules out me some how not using vtk.vtkDataSet() as a source of confusion.
Thanks for any help or known examples you can share.
You can still do it, but the address cannot be the address of a VTK data object. Which makes the feature much less useful, I know…
There is a work-around. You can disable VTK’s new numpy-friendly data object overrides by adding the following lines to the top of your program, before your “import vtk” statement:
Thanks for this! That allowed me to wrap the object. Good to know the source of the change, I’ll read more details soon.
We are focused on 9.5 for now, it would be great to have some recipe to do wrapping like this for 9.6 Doesn’t really matter how nice it looks b/c is buried in our infrastructure.
Thanks again!
Here is an other approach we tried recently that also works with ParaView.
You can create your Python object from a C++ object using vtkPythonUtil::GetObjectFromPointer. From there, you just need to make your object visible from your Python instance. Here is a full example:
#include <vtkPythonUtil.h>
#include <vtkSmartPyObject.h>
// ...
vtkNew<vtkPolyData> data;
// Create the python object
vtkSmartPyObject pyDataFromCpp = vtkPythonUtil::GetObjectFromPointer(data.GetPointer());
// Make it visible from python
PyObject* mainModule = PyImport_AddModule("__main__");
PyObject* mainDict = PyModule_GetDict(mainModule);
PyDict_SetItemString(mainDict, "pyDataFromPython", pyDataFromCpp);
// Python script
std::string script;
script += "print(type(pyDataFromPython))\n"; // available with name set above
// Run your script, ...
Note you don’t need here to disable anything so it may be more reliable and future-proof.