混合 VTK 和 SWIG Python
这是我的类:
#include <vtkPolyData>
class VTKUtilities
Mesh3D MeshfromVTKPolyData(vtkPolyData* pdmesh)
{
Mesh3D mesh;
//...
//my conversion code to do the actual conversion
//...
return mesh;
}
我试着用SWIG把这个转换成Python,但我在Python中调用我的函数时是这样做的:
import VTKUtilities
import vtk
pd = vtk.vtkPolyData()
VTKUtilities.MeshfromVTKPolyData(pd)
结果我遇到了这样的错误:
NotImplementedError: Wrong number of arguments... for VTKUtilities_MeshfromVTKPolyData
...
Possible prototypes are VTKUtilities::MeshfromVTKPolyData(vtkPolyData *);
我有读到一些关于类型映射的内容,但我以为我不需要去处理这些,因为SWIG应该能帮我搞定吧?
有人能告诉我在我的流程中缺少了什么,或者可能的解决办法吗?
2 个回答
0
这里有一个vtk.i,它为VTK的类提供了SWIG的类型映射和内存管理的接口,适用于你项目中从VTK对象派生的类,这些类是通过SWIG包装的。
代码
下面是完整的代码。这段代码经过了VTK 8和SWIG 3.7的测试。请注意,上面的链接中包含示例,并可能会有未来的更新。
/*
vtk.i a SWIG interface to VTK classes
Copyright (C) 2017 Burlen Loring
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
%{
#include <vtkPythonUtil.h>
%}
%include "exception.i"
/*---------------------------------------------------------------------------
macro: VTK_SWIG_INTEROP(vtk_t)
arguments:
vtk_t - a VTK class name that is used in the SWIG generated API.
The macro defines the typemaps needed for SWIG to convert to and
from VTK's Python bindings. Use this when your API containes pointers
to classes defined in VTK.
---------------------------------------------------------------------------*/
%define VTK_SWIG_INTEROP(vtk_t)
%{
#include <vtk_t##.h>
%}
%typemap(out) vtk_t*
{
$result = vtkPythonUtil::GetObjectFromPointer(
static_cast<vtkObjectBase*>($1));
}
%typemap(in) vtk_t*
{
$1 = static_cast<vtk_t*>(
vtkPythonUtil::GetPointerFromObject($input,#vtk_t));
if (!$1)
{
SWIG_exception(SWIG_TypeError,
"an object of type " #vtk_t " is required");
}
}
%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER) vtk_t*
{
$1 = vtkPythonUtil::GetPointerFromObject($input,#vtk_t) ? 1 : 0;
}
%enddef
/*---------------------------------------------------------------------------
macro: VTK_DERIVED(derived_t)
arguments:
derived_t - name of a class that derives from vtkObjectBase.
The macro causes SWIG to wrap the class and defines memory management hooks
that prevent memory leaks when SWIG creates the objects. Use this to wrap
VTK classes defined in your project.
---------------------------------------------------------------------------*/
%define VTK_DERIVED(derived_t)
%{
#include <derived_t##.h>
%}
%feature("ref") derived_t "$this->Register(nullptr);"
%feature("unref") derived_t "$this->UnRegister(nullptr);"
%newobject derived_t##::New();
%include <derived_t##.h>
%enddef
如果你的API使用了vtkObjectBase和vtkDataObject,你的SWIG .i文件应该包含:
VTK_SWIG_INTEROP(vtkObjectBase)
VTK_SWIG_INTEROP(vtkDataObject)
每个出现在你API中的VTK类都会有一个宏调用。
示例用法
如果你定义了一个从vtkObject或它的子类派生的类,叫做DataAdaptor,你的SWIG .i文件应该包含:
VTK_DERIVED(DataAdaptor)
请注意,你还需要为你类的API中任何VTK类调用VTK_SWIG_INTEROP,包括vtkObjectBase。
4
我成功地将参数为vtkPolyData的函数进行了封装,方法如下:
首先,你需要在swig的.i
文件中包含vtkPythonUtil:
%{
#include <vtkPythonUtil.h>
}%
接着,你需要在swig的.i
文件中映射vtkPolyData:
%typemap(out) vtkPolyData* {
PyImport_ImportModule("vtk");
$result = vtkPythonUtil::GetObjectFromPointer ( (vtkPolyData*)$1 );
}
%typemap(in) vtkPolyData* {
$1 = (vtkPolyData*) vtkPythonUtil::GetPointerFromObject ( $input, "vtkPolyData" );
if ( $1 == NULL ) { SWIG_fail; }
}
我发现这在ITK的itkVTKGlue中有相关内容。
最后,你需要将你的模块与vtkPythonCore
库链接起来。