SWIG 3包含带有模板化构造函数的untemplated类

时间:2014-10-15 19:08:19

标签: python c++ templates constructor swig

我们有一个带有模板化构造函数的未模板化的C ++类。我们能够使用SWIG 2来创建一个Python包装器,但是同样的代码在SWIG 3中失败了:包装器类的构造函数引发了AttributeError(“No constructor defined”)。我希望有人可以建议一个干净的修复或解决方法。

这是C ++标题的摘录:

class FootprintSet {
public:
    template <typename ImagePixelT>
    FootprintSet(image::Image<ImagePixelT> const& img,
                 Threshold const& threshold,
                 int const npixMin=1, bool const setPeaks=true);

    FootprintSet(geom::Box2I region);
...

和SWIG接口文件的主要部分:

%shared_ptr(lsst::afw::detection::FootprintSet);

%include "lsst/afw/detection/FootprintSet.h"

%define %footprintSetOperations(PIXEL)
%template(FootprintSet) FootprintSet<PIXEL>;
%enddef

%extend lsst::afw::detection::FootprintSet {
%footprintSetOperations(boost::uint16_t)
%footprintSetOperations(int)
%footprintSetOperations(float)
%footprintSetOperations(double)
}

我考虑过的一个原始解决方法是使用每个特化的显式版本替换标题中的模板化构造函数,例如:

class FootprintSet {
public:
#ifndef SWIG
    template <typename ImagePixelT>
    FootprintSet(image::Image<ImagePixelT> const& img,
                 Threshold const& threshold,
                 int const npixMin=1, bool const setPeaks=true);
#else
    FootprintSet(image::Image<boost::unit16> const& img,
                 Threshold const& threshold,
                 int const npixMin=1, bool const setPeaks=true);
    FootprintSet(image::Image<int> const& img,
                 Threshold const& threshold,
                 int const npixMin=1, bool const setPeaks=true);
    FootprintSet(image::Image<float> const& img,
                 Threshold const& threshold,
                 int const npixMin=1, bool const setPeaks=true);
    FootprintSet(image::Image<double> const& img,
                 Threshold const& threshold,
                 int const npixMin=1, bool const setPeaks=true);
#endif

    FootprintSet(geom::Box2I region);
...

或者(可能更好)在SWIG界面中添加类似的东西,而不是C ++标题。

尽管如此,我希望有一个更简单的解决方案。我们想更新到SWIG 3以获得C ++ 11支持,但这是一个重要的阻止程序。

2 个答案:

答案 0 :(得分:0)

编译器可能需要一些帮助来确定Image是模板化类型。尝试放typename

FootprintSet(typename image::Image<ImagePixelT> const& img, ...

答案 1 :(得分:0)

它确实似乎是SWIG的回归。这是一个简化的例子:

price@price-laptop:~/test $ cat test.h
#ifndef TEST_H
#define TEST_H

#include <iostream>
#include <typeinfo>

namespace test {

class Foo
{
public:
    template<typename T>
    Foo(T bar);
    ~Foo() {}
    void working() const {
        std::cout << "WORKING" << std::endl;
    }
};

}

#endif
price@price-laptop:~/test $ cat test.cc 
#include "test.h"

namespace test {

template <typename T>
Foo::Foo(T) {
    std::cout << typeid(T).name() << std::endl;
}

template Foo::Foo(int);

}

price@price-laptop:~/test $ cat test.i
%feature("autodoc", "1");
%module(package="test", docstring="test") testLib

%{
#include "test.h"
%}

%include "test.h"

%extend test::Foo {
     %template(Foo) Foo<int>;
}

price@price-laptop:~/test $ clang++ -shared -undefined dynamic_lookup -o libtest.dylib test.cc

使用SWIG 2.0.12:

price@price-laptop:~/test $ swig -python -c++ test.i
price@price-laptop:~/test $ clang++ -shared -undefined dynamic_lookup -o _testLib.so test_wrap.cxx -L. -ltest -I/usr/include/python2.7
price@price-laptop:~/test $ python -c "import testLib; testLib.Foo(1)"
i

使用SWIG 3.0.2,似乎将Foo::Foo视为普通函数,警告它没有返回类型,并忽略它:

price@price-laptop:~/test $ swig -python -c++ test.i
test.i:11: Warning 504: Function test::Foo::Foo(int) must have a return type. Ignored.
price@price-laptop:~/test $ clang++ -shared -undefined dynamic_lookup -o _testLib.so test_wrap.cxx -L. -ltest -I/usr/include/python2.7
price@price-laptop:~/test $ python -c "import testLib; testLib.Foo(1)"Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "testLib.py", line 82, in __init__
    def __init__(self, *args, **kwargs): raise AttributeError("No constructor defined")
AttributeError: No constructor defined

建议你踢上游。


编辑:这是fixed upstream