SWIG Python到C++:设置类型为map<string, int>的结构成员时出现TypeError
SWIG似乎在生成将结构体字段类型为map的绑定时出现了问题,导致在尝试将map字段设置为Python字典时出现类型错误。我是不是漏掉了什么错误?是个不被支持的用法?还是SWIG本身的bug?
首先是输出结果
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 > > > *'
这是我的测试案例:
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
#ifndef _TEST_H_
#define _TEST_H_
#include <string>
#include <map>
struct MyStruct
{
std::map<std::string, unsigned int> data;
};
#endif //_TEST_H_
test.cpp
#include "test.h"
run_test.py
import test
struct = test.MyStruct()
struct.data = { 'A':1, 'B':2 }
print struct.data
我用命令swig -python -c++ -o test_wrapper.cpp test.i来构建test_wrapper.cpp,编译其他所有文件,然后运行run_test.py。
作为一种变通办法,我可以明确地定义一个设置函数(void setData(const map<string, unsigned int>& data)
),这会生成不同的转换代码——它通过traits_asptr而不是SWIG_ConvertPtr来处理——看起来可以工作,但不太符合Python的风格!
编辑
这是我的.i文件,它将属性的获取和设置通过C++的getter和setter进行处理。我觉得这就是Nathan在他回答下方评论中提到的建议。
%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)
%}
};
1 个回答
1
当你在设置 struct.data
时,它其实是希望你给它一个 test.StringIntMap
,而不是一个 Python 的 dict
。
最简单的方法就是这样做:
struct.data = test.StringIntMap({ 'A':1, 'B':2 })