首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用SWIG扩展python中的模板化c++类以允许[]运算符

如何使用SWIG扩展python中的模板化c++类以允许[]运算符
EN

Stack Overflow用户
提问于 2014-03-30 04:47:16
回答 3查看 2.5K关注 0票数 6

我有一个模板化的c++数组类,它使用标准的向量类:

代码语言:javascript
复制
#include <vector>
#include <string>

using namespace std;

template<typename T>
class Array1D{
private:
    vector<T> data_; 
    int xsize_; 
public:
    Array1D(): xsize_(0) {};

    // creates vector of size nx and sets each element to t
    Array1D(const int& nx, const T& t): xsize_(nx) {
        data_.resize(xsize_, t);
    }

    T& operator()(int i) {return data_[i];}
    T& operator[](int i) {return data_[i];}
};

我的SWIG界面文件看起来像这样

代码语言:javascript
复制
%module test

%{ 
#define SWIG_FILE_WITH_INIT
#include "test.h"
%}

%include "std_vector.i"

// Array 1D Typemaps
// typemaps for standard vector<double>
namespace std{
%template(DoubleVector) vector<double>;
%template(IntVector) vector<int>;
}

%include "test.h"

%template(intArray1D) Array1D<int>;
%template(doubleArray1D) Array1D<double>;

%rename(__getitem__) operator[];
%extend Array1D<T>{
    T& __getitem__(int i) {
    return (*self)[i];
    }
 }

在创建模块并在python中创建一个Array1D之后,当我输入a2时,我得到以下错误:

代码语言:javascript
复制
TypeError: 'doubleArray1D' object does not support indexing

我猜是我的接口文件的extend部分出了问题。我不认为它是识别类型T。有没有关于如何让它工作的想法?

提前感谢!

EN

回答 3

Stack Overflow用户

发布于 2014-04-06 04:41:08

您可以扩展整个模板,而不必选择特定的类型。例如,按如下方式修改代码:

代码语言:javascript
复制
%module test

%{
#include <vector>
%}

%inline %{
template<typename T>
class Array1D{
private:
    std::vector<T> data_;
    size_t xsize_;
public:
    Array1D(): xsize_(0) {};

    // creates vector of size nx and sets each element to t
    Array1D(const size_t& nx, const T& t): xsize_(nx) {
        data_.resize(xsize_, t);
    }

    T& operator[](const size_t i) {return data_.at(i);}
};
%}

%extend Array1D {
   T __getitem__(size_t i) {
    return (*$self)[i];
  }
}

%template(intArray1D) Array1D<int>;
%template(doubleArray1D) Array1D<double>;

它的工作方式与您希望的一样,因为SWIG本身在生成包装器时会扩展并填充T的类型:

代码语言:javascript
复制
In [1]: import test

In [2]: a=test.intArray1D(10,1)

In [3]: a[0]

Out[3]: 1

In [4]: a[10]

terminate called after throwing an instance of 'std::out_of_range'
  what():  vector::_M_range_check
zsh: abort      ipython

注意:我从int换成了size_t,因为它们并不总是同义词,而且.at()而不是[],因为前者会抛出一个无效的索引,而不是调用未定义的行为。实际上,你可以免费使用SWIG的默认异常库来做“聪明”的事情:

代码语言:javascript
复制
%module test

%{
#include <vector>
%}

%include <std_except.i>

%inline %{
template<typename T>
class Array1D{
private:
    std::vector<T> data_;
    size_t xsize_;
public:
    Array1D(): xsize_(0) {};

    // creates vector of size nx and sets each element to t
    Array1D(const size_t& nx, const T& t): xsize_(nx) {
        data_.resize(xsize_, t);
    }

    T& operator[](const size_t i) {return data_.at(i);}
};
%}

%extend Array1D {
   T __getitem__(size_t i) throw(std::out_of_range) {
    return (*$self)[i];
  }
}

%template(intArray1D) Array1D<int>;
%template(doubleArray1D) Array1D<double>;

足够(两行更改)来获得Python,而不是C++ exception,crash或其他UB。

票数 6
EN

Stack Overflow用户

发布于 2014-04-01 07:37:27

您可以分别扩展每种类型,如下所示:

代码语言:javascript
复制
%extend doubleArray1D {

请注意,扩展是虚拟的,因为它只是告诉SWIG为额外的函数生成代码,这些函数将成为导出类的一部分,但这些函数只能访问您的c++类的公共接口。

如果你有一大堆模板实例,你可以定义和使用SWIG宏:

代码语言:javascript
复制
%define ArrayExtend(name, T)
%extend name<T> {
    T& __getitem__(int i) {
    return (*self)[i];
    }
 }
%enddef

ArrayExtend(Array1D, double)
ArrayExtend(Array1D, int)
票数 3
EN

Stack Overflow用户

发布于 2020-03-06 18:07:01

要提供更通用的解决方案:

%define ArrayExtendVal(name, T) %extend name { T getitem(int i) { return (*self)[i]; } } %enddef %define ArrayExtendRef(name, T) %extend name { T& getitem(int i) { return (*self)[i]; } } %enddef %define ArrayExtendConstRef(name, T) %extend name { const T& getitem(int i) { return (*self)[i]; } } %enddef ... %ignore myNamespace::myClass::operator[] %include "my_class.h" ArrayExtendVal(myClass, double); ArrayExtendRef(myClass, double); ArrayExtendConstRef(myClass, double);

请注意其他答案中缺少的%ignore指令。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22736700

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档