![](/img/trans.png)
[英]SWIG - How to wrap to python a class with a constructor that takes a 'const double*'
[英]SWIG 3 wrap untemplated class with templated constructor
我们有一个带有模板构造函数的非模板C ++类。 我们可以使用SWIG 2来制作Python包装器,但是在SWIG 3中,相同的代码将失败:包装器类的构造函数引发AttributeError(“未定义构造函数”)。 我希望有人可以提出干净的修复或解决方法。
这是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支持,但这是一个重要的阻止因素。
编译器可能需要一些帮助,才能确定Image
是模板化类型。 尝试输入typename
:
FootprintSet(typename image::Image<ImagePixelT> const& img, ...
在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
建议您向上游踢。
编辑:这已修复上游 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.