Swig命名空间错误?不是一个有效的基类

swig namespace error? not a valid base class

本文关键字:一个 有效 基类 错误 命名空间 Swig      更新时间:2023-10-16

我使用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

任何想法?

好的,所以经过多次故障排除后,我弄清楚了。当我将代码放入非std名称空间后,这些问题就出现了,当我的所有代码都在std名称空间中时,上面的。I文件可以正常工作。

有两个问题。首先,基类必须在. I文件的显式中定义,这在文档中有提到,但我错过了。而且,SWIG显然不支持定义了构造函数的基类。向StopPow类添加方法StopPow()会导致从它继承的三个类出现"错误:'StopPow'不是一个有效的基类"

这里是工作的停止点。

// 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"

SWIG用构造函数/析构函数处理基类很好。问题是名称空间与类名称相同。示例(用于Python):

demo.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"

demo.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)