关于c ++:混合VTK和SWIG Python

mix VTK and SWIG Python

这是我的课:

1
2
3
4
5
6
7
8
9
10
11
12
#include <vtkPolyData>

class VTKUtilities

Mesh3D MeshfromVTKPolyData(vtkPolyData* pdmesh)
{
   Mesh3D mesh;
   //...
   //my conversion code to do the actual conversion
   //...
   return mesh;
}

我试着用swig把这个包装到python上但是我尝试在python中这样调用我的函数:

1
2
3
4
5
import VTKUtilities
import vtk

pd = vtk.vtkPolyData()
VTKUtilities.MeshfromVTKPolyData(pd)

我会得到错误,比如:

1
2
3
NotImplementedError: Wrong number of arguments... for VTKUtilities_MeshfromVTKPolyData
...
Possible prototypes are VTKUtilities::MeshfromVTKPolyData(vtkPolyData *);

我一直在读一些关于打印地图的东西,但我想我不必再为这件事操心了,因为斯威格应该为我处理这个问题?有人能告诉我我的流程中遗漏了什么吗?可能有什么解决方法吗?


我通过这样做成功地包装了参数为vtkpolydata的函数:

首先,您必须将vtkpythonutil包含在swig .i文件中:

1
2
3
4
5
%{

#include <vtkPythonUtil.h>

}%

然后,您必须映射swig .i文件中的vtkpolydata:

1
2
3
4
5
6
7
8
9
10
11
12
13
 %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链接起来。


这里是一个vtk.i,为vtk的类提供swig类型映射,为在项目中定义的类提供内存管理钩子,这些类是由swig包装的vtk对象派生的。

代码

这是完整的代码。这是用vtk 8和swig 3.7测试的。请注意,上面的链接包含示例,并且可能包含将来的更新。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/*
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和vtkdata对象,那么swig.i文件将包括:

1
2
VTK_SWIG_INTEROP(vtkObjectBase)
VTK_SWIG_INTEROP(vtkDataObject)

在您的API中,每个VTK类将有一个宏调用。

示例用法

如果您定义一个从vtkobject派生的类或它的一个子类dataadapter,那么swig.i文件将包括:

1
VTK_DERIVED(DataAdaptor)

注意,您还需要为类的API中的任何vtk类(包括vtkobjectbase)调用vtk_swig_interop。