为什么 swig 将 python 列表无缝转换为 std::vector 而不是 std::set? [英] why swig casts python list to std::vector seamlessly and not std::set?

查看:27
本文介绍了为什么 swig 将 python 列表无缝转换为 std::vector 而不是 std::set?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了将基本的 C++ 类扩展到 python,我用 swig 做了一些试验.我发现了一个行为与到目前为止我无法解释的集合的使用有关.这是我的脚本:

MyClass.h:

#pragma once#include <设置>#include <向量>我的课堂{民众:我的课();void setSTLVector(const std::vector &vector);void setSTLSet(const std::set<int> &set);私人的:std::vector_stlVector;std::set_stlSet;};

MyClass.cpp:

#include "MyClass.h"我的班级::我的班级(){}void MyClass::setSTLVector(const std::vector &vector){_stlVector = 向量;}void MyClass::setSTLSet(const std::set<int> &set){_stlSet = 设置;}

MyClass.i:

%module MyClass%{#include "MyClass.h"%}%include %include "std_vector.i"%template(IntVector) std::vector;%include "std_set.i"%template(IntSet) std::set;%include "MyClass.h"

编译时一切正常(似乎).在将我的扩展程序运行到 python 时,我的误解开始了.确实:

在[1]中:导入MyClass在 [2] 中:cls = MyClass.MyClass()在 [3]: cls.setSTLVector([1,2,3,4])

至少按照我的预期完美运行,即 python 整数列表 在内部被 castedstd::vector.对于集合:

在[1]中:导入MyClass在 [2] 中:cls = MyClass.MyClass()在 [3]: cls.setSTLVector({1,2,3,4})

触发以下错误:

TypeError: 在方法 'MyClass_setSTLSet' 中,类型为 'std::set< 的参数 2int,std::less>const &'

这个错误可能与我使用我在 swig 中定义的类型声明一个集合时遇到的另一个错误有关:

在[1]中:导入MyClass在 [2]: cls = MyClass.IntSet({1,2,3,4})

给出:

NotImplementedError:重载函数new_IntSet"的参数数量或类型错误.可能的 C/C++ 原型是:std::set

你知道我做错了什么还是这是正常行为?

解决方案

std_set.i 的类型映射不直观地期望 Python list 作为输入而不是 设置.

<预><代码>>>>导入我的课堂>>>cls = MyClass.MyClass()>>>cls.setSTLVector([1,2,3,4]) # 有效>>>cls.setSTRSet([1,2,3,4]) # 有效>>>cls.setSTLSet({1,2,3,4}) # 不起作用回溯(最近一次调用最后一次):文件<stdin>",第 1 行,在 <module> 中文件C:\MyClass.py",第 385 行,在 setSTLSet 中返回 _MyClass.MyClass_setSTLSet(self, set)类型错误:在方法MyClass_setSTLSet"中,std::set<"类型的参数 2int,std::less>const &'**强文本**

您必须定义自己的自定义类型映射才能将 set 作为输入.

I make some trials with swig in order to extend basic C++ class to python. I found a behavior related to the use of sets that I can't explain so far. Here are my scripts:

MyClass.h:

#pragma once
#include <set>
#include <vector>

class MyClass
{
public:
    MyClass();
    void setSTLVector(const std::vector<int> &vector);
    void setSTLSet(const std::set<int> &set);

private:
    std::vector<int> _stlVector;
    std::set<int> _stlSet;
};

MyClass.cpp:

#include "MyClass.h"

MyClass::MyClass()
{
}

void MyClass::setSTLVector(const std::vector<int> &vector)
{
    _stlVector = vector;
}

void MyClass::setSTLSet(const std::set<int> &set)
{
    _stlSet = set;
}

MyClass.i:

%module MyClass

%{
    #include "MyClass.h"
%}

%include <typemaps.i>

%include "std_vector.i"
%template(IntVector) std::vector<int>;

%include "std_set.i"
%template(IntSet) std::set<int>;

%include "MyClass.h"

when compiling everything is (seems) OK. My misunderstanding begins when running my extension into python. Indeed:

In [1]: import MyClass
In [2]: cls = MyClass.MyClass()
In [3]: cls.setSTLVector([1,2,3,4])

works perfectly at least how I expect i.e. the python list of integers is casted internally to a std::vector<int>. For the set:

In [1]: import MyClass
In [2]: cls = MyClass.MyClass()
In [3]: cls.setSTLVector({1,2,3,4})

triggers the following error:

TypeError: in method 'MyClass_setSTLSet', argument 2 of type 'std::set< int,std::less< int >,std::allocator< int > > const &'

This error being probably related to another I have when I declare a set using the type I defined in swig:

In [1]: import MyClass
In [2]: cls = MyClass.IntSet({1,2,3,4})

which gives:

NotImplementedError: Wrong number or type of arguments for overloaded function 'new_IntSet'.
  Possible C/C++ prototypes are:
    std::set< int >::set(std::less< int > const &)
    std::set< int >::set()
    std::set< int >::set(std::set< int > const &)

Would you have any idea about what I am doing wrong or is that a normal behavior ?

解决方案

The typemaps for std_set.i unintuitively expect a Python list as input and not a set.

>>> import MyClass
>>> cls = MyClass.MyClass()
>>> cls.setSTLVector([1,2,3,4]) # works
>>> cls.setSTLSet([1,2,3,4])    # works
>>> cls.setSTLSet({1,2,3,4})    # doesn't work
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\MyClass.py", line 385, in setSTLSet
    return _MyClass.MyClass_setSTLSet(self, set)
TypeError: in method 'MyClass_setSTLSet', argument 2 of type 'std::set< int,std::less< int >,std::allocator< int > > const &'**strong text**

You would have to define your own custom typemap to take a set as input.

这篇关于为什么 swig 将 python 列表无缝转换为 std::vector 而不是 std::set?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆