python内置数据结构和stl_用SWIG向Python提供C++里STL的容器

用SWIG向Python提供C++里STL的容器

2018-03-06 18:10:30 +08

字数:1226

标签:

Python

C

在Python项目中使用C/C++的代码,除了少数场景,其它都有数据交换的需求。

而C++的vector、map等,则是常见的数据容器。

本文介绍如何利用SWIG,在Python中调用STL的string、vector和map。

string ¶

C++的string可以在interface文件里声明时,自动转换成Python文件的str。

但是需要在%module ...下,声明%include "std_string.i"。

%module example_string

%include "std_string.i"

%{

std::string echo(std::string msg);

%}

std::string echo(std::string msg);

如果只是一些内容简单、结构复杂的数据交换,可以考虑以某种方式序列化为字符串,到上层再解析为Python层的数据结构。

这里展示的是一个返回自身的echo函数,实现如下:

#include

using namespace std;

string echo(string msg) {

return msg;

}

在Python中,调用结果如下:

>>> import example_string

>>> msg = example_string.echo('message')

>>> msg

'message'

>>> isinstance(msg, str)

True

可见,传入和返回,都是Python自带的str类型,非常方便。

vector ¶

vector应该是最常见的顺序容器了。

它比string要更麻烦一层,因为模板类是特殊的,需要用%template声明一下。

%module example_vector

%include "std_string.i"

%include "std_vector.i"

%{

using namespace std;

vector vector_int2str(vector input);

%}

namespace std {

%template(StringVector) vector;

%template(IntVector) vector;

}

using namespace std;

vector vector_int2str(vector input);

Python层会自动生成StringVector和IntVector这两个类,作为类型的替代。

这两个类的命名可以随意,它们都实现了list的相关协议,可以当作list来使用。

示例中的vector_int2str函数,就是把vector的int转换为string,实现如下:

#include

#include

using namespace std;

vector vector_int2str(vector input) {

vector result;

for (vector::const_iterator it = input.begin();

it != input.end();

++it) {

result.push_back(to_string(*it));

}

return result;

}

然而,实际在Python层获取返回值时,却是tuple类型。

传入时,也可直接使用list或tuple等类型——这大概就是动态语言、鸭子类型的魅力吧。

>>> import example_vector

>>> data = example_vector.vector_int2str([1, 2, 3])

>>> data

('1', '2', '3')

>>> isinstance(data, tuple)

True

map ¶

map是最常见的的关联容器。

和vector一起,可以简单表达一切线性数据结构。

与vector类似,使用时也需要用%template声明。

此外,它还有一个特殊情况。

%module example_map

%include "std_string.i"

%include "std_map.i"

%{

using namespace std;

map reverse_map(map input);

%}

namespace std {

%template(Int2strMap) map;

%template(Str2intMap) map;

}

using namespace std;

map reverse_map(map input);

上面的形式,和vector类似。

其中,reverse_map反转了映射关系,示例代码如下:

#include

#include

#include

using namespace std;

map reverse_map(map input) {

map result;

for (map::const_iterator it = input.begin();

it != input.end();

++it) {

result[it->second] = it->first;

}

return result;

}

特殊情况就是,虽然Str2intMap和Int2strMap也实现了dict的协议,但是使用时不能直接用Python的dict。

str2int = example_map.Str2intMap()

str2int['1'] = 1

str2int['2'] = 2

str2int['3'] = 3

result = example_map.reverse_map(str2int)

assert isinstance(result, example_map.Int2strMap)

for key, value in result.items():

assert str2int[value] == key

这就有些不方便了。

不过,虽然没有vector方便,但还是可以接受。

换个角度看,也许vector才是特殊情况吧。

总结 ¶

其它数据结构,比如list、set等,都有对应的转换方式,这里不一一介绍。

C++ class

C++ Library file

SWIG Interface library file

std::auto_ptr

memory

std_auto_ptr.i

std::deque

deque

std_deque.i

std::list

list

std_list.i

std::map

map

std_map.i

std::pair

utility

std_pair.i

std::set

set

std_set.i

std::string

string

std_string.i

std::vector

vector

std_vector.i

std::array

array (C++11)

std_array.i

std::shared_ptr

shared_ptr (C++11)

std_shared_ptr.i

在这些内置*.i的支持下,Python与C++的数据交换也变得轻松起来。

参考 ¶

以下是相关的官网文档:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值