9

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

 4 years ago
source link: https://note.qidong.name/2018/03/swig-stl-to-python/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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

2018-03-06 18:10:30 +08  字数:1226  标签: Python C

在Python项目中使用C/C++的代码,除了少数场景,其它都有数据交换的需求。 而C++的vectormap等,则是常见的数据容器。

本文介绍如何利用SWIG,在Python中调用STL的stringvectormap

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 <string>

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<string> vector_int2str(vector<int> input);
%}

namespace std {
  %template(StringVector) vector<string>;
  %template(IntVector) vector<int>;
}

using namespace std;

vector<string> vector_int2str(vector<int> input);

Python层会自动生成StringVectorIntVector这两个类,作为类型的替代。 这两个类的命名可以随意,它们都实现了list的相关协议,可以当作list来使用。

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

#include <string>
#include <vector>

using namespace std;

vector<string> vector_int2str(vector<int> input) {
    vector<string> result;
    for (vector<int>::const_iterator it = input.begin();
        it != input.end();
        ++it) {
        result.push_back(to_string(*it));
    }
    return result;
}

然而,实际在Python层获取返回值时,却是tuple类型。 传入时,也可直接使用listtuple等类型——这大概就是动态语言、鸭子类型的魅力吧。

>>> 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<int, string> reverse_map(map<string, int> input);
%}

namespace std {
  %template(Int2strMap) map<int, string>;
  %template(Str2intMap) map<string, int>;
}

using namespace std;

map<int, string> reverse_map(map<string, int> input);

上面的形式,和vector类似。 其中,reverse_map反转了映射关系,示例代码如下:

#include <string>
#include <vector>
#include <map>

using namespace std;

map<int, string> reverse_map(map<string, int> input) {
    map<int, string> result;
    for (map<string, int>::const_iterator it = input.begin();
        it != input.end();
        ++it) {
        result[it->second] = it->first;
    }
    return result;
}

特殊情况就是,虽然Str2intMapInt2strMap也实现了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才是特殊情况吧。

总结

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

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++的数据交换也变得轻松起来。

参考

以下是相关的官网文档:


Recommend

  • 10

    在C语言程序开发中,若是遇到了不能确定长度的数据类型结构,链表常常是一个不错的选择,但是C语言并未提供原生的链表结构,程序员不得不自己设计一套链表管理机制。虽说开源社区也提供了不少好用的通用设计,但毕竟不是C语言原生的语法,统一性有所欠缺。C++大...

  • 7
    • note.qidong.name 4 years ago
    • Cache

    在setup.py中配置SWIG模块

    在setup.py中配置SWIG模块 2018-03-20 16:17:05 +08  字数:1883  标签: Python C

  • 4
    • note.qidong.name 4 years ago
    • Cache

    编译运行SWIG的example代码样例

    编译运行SWIG的example代码样例 2018-01-11 18:09:55 +08  字数:1711  标签: Python C...

  • 6

    Windows中VS code debug时无法查看C++ STL容器内容 首先,你很可能用的是x64版本的Windows。 我发现一个有效的解决方法,但在x64版本的Windows上安装MinGW时,虽然官方推荐MinGW版本的是x86_64的,但实践后发现如果选择安装 x86_64的, 很可能De...

  • 6
    • help.dreamhost.com 3 years ago
    • Cache

    How to install a newer version of SWIG

    How to install a newer version of SWIG Overview To run the commands in this article, you must log into your server via SSH with your Shell user. View the following articles f...

  • 5
    • blog.csdn.net 3 years ago
    • Cache

    C++——STL容器

    首先,适配器的概念 适配器的意思就是将某些已经存在的东西进行限制或者组合变成一个新的东西,这个新的东西体现一些新的特性,但底层都是由一些已经存在的东西实现的。 STL中的容器

  • 6
    • hkvision.cn 3 years ago
    • Cache

    SWIG 以Python为例

    本文为原创文章,转载注明出处,欢迎关注网站https://hkvision.cnSWIG用途SWIG是用于开发C/C++与Java,Python,Perl,C#等高级语言之间接口的框架,利用这个框架,我们可以很方便...

  • 8

    本文为原创文章,转载注明出处,欢迎关注网站https://hkvision.cn先允许我吐槽一下海康威视的SDK有多难用SWIG编译先声明我编译的是linux版本的,环境是ubuntu 18.04,还没有开始做...

  • 8
    • dreamgoing.github.io 2 years ago
    • Cache

    STL容器简介

    C++ STL容器简介array,list,tree,stack,queue,hash table,set,map,这些数据结构可以分为序列式(sequence)和关联式(associative)两种。序列式和关联式容器序列式(Sequence Containers)

  • 11
    • blog.51cto.com 2 years ago
    • Cache

    STL之stack等容器适配器

    这个应该是我们STL最后一个博客了,今天是三个数据结构,分别是stack,queue和优先级队列,从某种意义上来说,他们不叫容器,叫做容器适配器.我们先来认识一下就可以了.容器适配器我们看一下他们的模板参数你就会明白了,第二个参数是一个Container...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK