简体   繁体   English

SWIG Python to C ++:TypeError试图设置类型为map的struct成员<string, int>

[英]SWIG Python to C++: TypeError trying to set struct member of type map<string, int>

SWIG seems to be generating incorrect bindings for converting a struct field of type map, resulting in a TypeError trying to set the map field to a python dictionary. SWIG似乎为转换类型map的struct字段生成了错误的绑定,导致TypeError尝试将map字段设置为python字典。 Is there an error I am missing? 我错过了错误吗? an unsupported use-case? 一个不受支持的用例? a bug in SWIG? SWIG中的一个错误?

First the output 首先是输出

Traceback (most recent call last):
  File ".\use_test.py", line 4, in <module>
    struct.data = { 'A':1, 'B':2 }
  File "C:\Users\kmahan\Projects\SwigTest\test.py", line 150, in <lambda>
    __setattr__ = lambda self, name, value: _swig_setattr(self, MyStruct, name, value)
  File "C:\Users\kmahan\Projects\SwigTest\test.py", line 49, in _swig_setattr
    return _swig_setattr_nondynamic(self,class_type,name,value,0)
  File "C:\Users\kmahan\Projects\SwigTest\test.py", line 42, in _swig_setattr_nondynamic
    if method: return method(self,value)
TypeError: in method 'MyStruct_data_set', argument 2 of type 'std::map< std::string,unsigned int,std::less< std::string >,std::allocator< std::pair< std::string const,unsigned int > > > *'

And here is my test case: 这是我的测试用例:

test.i test.i

%module test

%include "std_string.i"
%include "std_map.i"

namespace std {
    %template(StringIntMap) map<string, unsigned int>;
}

%{
#include "test.h"
%}

%include "test.h"

test.h test.h

#ifndef _TEST_H_
#define _TEST_H_

#include <string>
#include <map>

struct MyStruct 
{
    std::map<std::string, unsigned int> data;
};

#endif //_TEST_H_

test.cpp TEST.CPP

#include "test.h"

run_test.py run_test.py

import test

struct = test.MyStruct()
struct.data = { 'A':1, 'B':2 }

print struct.data

I build test_wrapper.cpp with swig -python -c++ -o test_wrapper.cpp test.i, compile everything else, and run run_test.py. 我使用swig -py ++ -c ++ -o test_wrapper.cpp test.i构建test_wrapper.cpp,编译其他所有内容,然后运行run_test.py。

As a workaround I can explicitly define a setter instead ( void setData(const map<string, unsigned int>& data) ) which generates different conversion code -- it goes through traits_asptr instead of SWIG_ConvertPtr -- and seems to work but is not very pythonic! 作为一种解决方法,我可以显式定义一个setter( void setData(const map<string, unsigned int>& data) ),它生成不同的转换代码 - 它通过traits_asptr而不是SWIG_ConvertPtr - 似乎工作但不是很Python的!

EDIT 编辑

Here is my .i file that pipes gets and sets of the attribute itself to C++ getters and setters. 这是我的.i文件,管道获取和属性本身设置为C ++ getter和setter。 I think this is what Nathan suggested in the comment below his answer. 我认为这是内森在他的回答下面的评论中所建议的。

%module test

%include "std_string.i"
%include "std_map.i"

namespace std {
    %template(StringIntMap) map<string, unsigned int>;
}

struct MyStruct 
{
    const std::map<std::string, unsigned int>& getData() const;
    void setData(const std::map<std::string, unsigned int>&);

    %pythoncode %{
        __swig_getmethods__["data"] = getData
        __swig_setmethods__["data"] = setData
        if _newclass:
            data = _swig_property(getData, setData)
    %}
};

When you're setting struct.data , it's expecting a test.StringIntMap , not a python dict . 当你设置struct.data ,它需要一个test.StringIntMap ,而不是一个python dict

The easiest thing is for you to do this: 最简单的事情是你这样做:

struct.data = test.StringIntMap({ 'A':1, 'B':2 })

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM