0

我正在使用 SWIG 来包装 C++ 库。我收到一个错误,我认为这与我使用命名空间有关,但我不确定。不幸的是,SWIG 的文档似乎都集中在内联文档上,我不知道它从我的头文件中提取了什么。

这是我的 .i 文件:

%module cStopPow
%{
    #include "../src/StopPow.h"
    #include "../src/StopPow_SRIM.h"
    #include "../src/StopPow_LP.h"
    #include "../src/StopPow_BetheBloch.h"
%}

%include "cpointer.i"
%pointer_functions(int, intp);
%pointer_functions(float, floatp);

%include "std_vector.i"
#include <vector>
// Instantiate templates
namespace std {
   %template(IntVector) vector<int>;
   %template(FloatVector) vector<float>;
}


%include "std_string.i"
#include <string>
%include "../src/StopPow.h"
%include "../src/StopPow_SRIM.h"
%include "../src/StopPow_LP.h"
%include "../src/StopPow_BetheBloch.h"

这是一个裁剪的示例标题(它们的定义都非常相似):

#include ...

namespace StopPow
{

class StopPow_BetheBloch : StopPow
{ ...

其中三个类扩展了 StopPow。该库在 C++ 下编译良好,但 SWIG 给了我以下错误:

swig -java -c++ StopPow.i
../src/StopPow_BetheBloch.h:26: Warning 319: No access specifier given for base class 'StopPow' (ignored).
../src/StopPow_SRIM.h:27: Error: 'StopPow' is not a valid base class.
../src/StopPow.h:28: Error: See definition of 'StopPow'.
../src/StopPow_SRIM.h:27: Warning 401: Nothing known about base class 'StopPow'. Ignored.
../src/StopPow_LP.h:27: Error: 'StopPow' is not a valid base class.
../src/StopPow.h:28: Error: See definition of 'StopPow'.
../src/StopPow_LP.h:27: Warning 401: Nothing known about base class 'StopPow'. Ignored.
../src/StopPow_BetheBloch.h:26: Error: 'StopPow' is not a valid base class.
../src/StopPow.h:28: Error: See definition of 'StopPow'.
make: *** [StopPow] Error 6

有任何想法吗?

4

2 回答 2

0

好的,经过多次故障排除后,我发现了这一点。这些问题是在我将代码放入非标准命名空间后出现的,当我的所有代码都在标准中时,上面的 .i 文件有效。

有两个问题。首先,必须在 .i 文件中明确定义基类,这在文档中有所提及,但我错过了。此外,显然 SWIG 不支持定义了构造函数的基类。向 StopPow 类添加方法 StopPow() 会导致从它继承的三个类的“错误:'StopPow' 不是有效的基类”。

这是正在工作的 StopPow.i:

// StopPow.i - SWIG interface
%module cStopPow
%{
    #include "../src/StopPow.h"
    #include "../src/StopPow_SRIM.h"
    #include "../src/StopPow_LP.h"
    #include "../src/StopPow_BetheBloch.h"
%}

%include "cpointer.i"
%pointer_functions(int, intp);
%pointer_functions(float, floatp);

%include "std_vector.i"
#include <vector>
// Instantiate templates
namespace std {
   %template(IntVector) vector<int>;
   %template(FloatVector) vector<float>;
}

%include "std_string.i"
#include <string>

//%nspace StopPow::StopPow;
//%nspace StopPow::StopPow_LP;

// Need to define the base class:
namespace StopPow
{
class StopPow {
public:
    //StopPow();
    virtual float dEdx_MeV_um(float E) = 0;
    virtual float dEdx_MeV_mgcm2(float E) = 0;
    virtual float get_Emin() = 0;
    virtual float get_Emax() = 0;
    float dEdx(float E);
    float Eout(float E, float x);
    float Ein(float E, float x);
    float Thickness(float E1, float E2);
    float get_dx();
    void set_dx(float new_dx);
    int get_mode();
    void set_mode(int new_mode);

    static const float DEFAULT_DX;
    static const float DEFAULT_DRHOR;
    static const int MODE_LENGTH;
    static const int MODE_RHOR;
};
};

%include "../src/StopPow_SRIM.h"
%include "../src/StopPow_LP.h"
%include "../src/StopPow_BetheBloch.h"
于 2013-04-03T19:17:47.763 回答
0

SWIG 可以很好地处理带有构造函数/析构函数的基类。问题是有一个与类同名的命名空间。示例(对于 Python):

演示.i

%module demo

%begin %{
#pragma warning(disable:4127 4100 4211 4701 4706)
%}

%{
#include "demo.h"
%}

%include <std_vector.i>
%include <std_string.i>
%template(IntVector) std::vector<int>;
%include "demo.h"

演示.h

#include <iostream>
#include <string>
#include <vector>

namespace C {
    class A {
    public:
        A() { std::cout << __FUNCSIG__ << std::endl; }
        virtual std::vector<int> func(int a, int b) { return std::vector<int>(a,b); }
        std::string func2() { return std::string("From A"); }
        virtual ~A()  { std::cout << __FUNCSIG__ << std::endl; }
    };
    class B : public A {
    public:
        B() { std::cout << __FUNCSIG__ << std::endl; }
        std::vector<int> func(int a, int b) { return std::vector<int>(b,a); }
        std::string func3() { return std::string("From B"); }
        ~B()  { std::cout << __FUNCSIG__ << std::endl; }
    };
}

结果

构建和运行在 SWIG 代码生成期间显示错误,但仍可成功编译。

结果有两个问题:

  • B实例不知道基类A
  • 实例在B删除时不会调用其析构函数。

输出:

C:\>swig -c++ -python demo.i
demo.h(13) : Error: 'A' is not a valid base class.
demo.h(8) : Error: See definition of 'A'.
demo.h(13) : Warning 401: Nothing known about base class 'A'. Ignored.

C:\>cl /EHsc /LD /W4 /MD demo_wrap.cxx /I%PYTHON_ROOT%\include /nologo -link /nologo /LIBPATH:%PYTHON_ROOT%\libs /OUT:_demo.pyd
demo_wrap.cxx
   Creating library demo_wrap.lib and object demo_wrap.exp

C:\>py -3
Python 3.3.0 (v3.3.0:bd8afb90ebf2, Sep 29 2012, 10:57:17) [MSC v.1600 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import demo
>>> a=demo.A()
__cdecl A::A::A(void)
>>> a.func(3,4)
(4, 4, 4)
>>> a.func2()
'From A'
>>> b=demo.B()
__cdecl A::A::A(void)
__cdecl A::B::B(void)
>>> b.func(3,4)
(3, 3, 3, 3)
>>> b.func2()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File ".\demo.py", line 167, in <lambda>
    __getattr__ = lambda self, name: _swig_getattr(self, B, name)
  File ".\demo.py", line 55, in _swig_getattr
    raise AttributeError(name)
AttributeError: func2
>>> b.func3()
'From B'
>>> del a
__cdecl A::A::~A(void)
>>> del b
>>>

命名空间更改为后的输出C

C:\>swig -c++ -python demo.i

C:\>cl /EHsc /LD /W4 /MD demo_wrap.cxx /I%PYTHON_ROOT%\include /nologo -link /nologo /LIBPATH:%PYTHON_ROOT%\libs /OUT:_demo.pyd
demo_wrap.cxx
   Creating library demo_wrap.lib and object demo_wrap.exp

C:\>py -3
Python 3.3.0 (v3.3.0:bd8afb90ebf2, Sep 29 2012, 10:57:17) [MSC v.1600 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import demo
>>> a=demo.A()
__cdecl C::A::A(void)
>>> a.func(3,4)
(4, 4, 4)
>>> a.func2()
'From A'
>>> b=demo.B()
__cdecl C::A::A(void)
__cdecl C::B::B(void)
>>> b.func(3,4)
(3, 3, 3, 3)
>>> b.func2()
'From A'
>>> b.func3()
'From B'
>>> del a
__cdecl C::A::~A(void)
>>> del b
__cdecl C::B::~B(void)
__cdecl C::A::~A(void)
于 2013-04-06T16:26:21.117 回答