python - SWIG 3 使用模板化构造函数包装未模板化的类

标签 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 接口(interface)文件的主要部分:

%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)
}

我考虑过的一个粗略的解决方法是用每个专门化的显式版本替换 header 中的模板化构造函数,例如:

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 接口(interface)中放置类似的东西,而不是 C++ header 。

不过,我希望有一个更简单的解决方案。我们想更新到 SWIG 3 以获得 C++11 支持,但这是一个重要的障碍。

最佳答案

它似乎确实是 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 .

关于python - SWIG 3 使用模板化构造函数包装未模板化的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26390195/

相关文章:

python - 无法使用pygame在循环内连续播放mp3文件?

c++ - 带有空主体的while循环检查 volatile 整数-这是什么意思?

C++:涉及继承和 "using"时的方法重载

C++模板函数指针

c++ - C++模板中的百分号(%)和尖锐符号(#)是什么意思

Python Websocket 模块继续启动未被杀死的进程,导致内存问题

python - 我应该如何处理这个IndexError

c++ - C/C++ : double constants in class are inaccurate

c++ - 为什么构造不完整类型的 std::unique_ptr 编译?

python - 如何检测键盘模块的按键按下情况?