swig 实践(python & c/c++)(一)

前言

随便写点,不保持更新,构想是先简单说些实践的东西(这里就是python和c/c++),当然也可以支持R,C#,D,Go..这些,后面具体说一下swig这个东西(当然如果保持更新的话)。

当然我们又不能不先肤浅的谈一下swig,最直接的认识就是先上一个图,
swig.JPG

它可以用来连接(包装)其它的语言,以便发挥它们各自的特性。其实大多数情况下知道这个就已经够了,然后会简单使用一下就可以,那些大的框架里面用的比较多,譬如时下流行的神经网络框架Tensorflow,Caffe这些,在沟通后端和前端的语言时,就会大量用到。

开始

然后就从简单的事例讲起,先说安装,手边在用windows,就用这个说明就好了,毕竟对于经常用Linux的,基本上git,文档一看就懂的。
win的话从这里下载:http://prdownloads.sourceforge.net/swig/swigwin-3.0.12.zip
然后在环境变量配置一下,终端swig测试一下就知道可以没有。同时保持有python和C/C++的环境。

现在就可以正式开始了,我们假定构造一个环境:有一个简单c/c++的文件(一般就是写点效率代码,算法底层这种的),然后尝试着用python调用。
过程是这样的:

1.搞一个c/c++代码:

/*File:test.c*/
void quick_sort(int s[], int l, int r)
{
    if (l < r)
    {
        int i = l, j = r, x = s[l];
        while (i < j)
        {
            while (i < j && s[j] >= x)//从右到左找到第一个小于x的数  
                j--;
            if (i < j)
                s[i++] = s[j];

            while (i < j && s[i] <= x)//从左往右找到第一个大于x的数  
                i++;
            if (i < j)
                s[j--] = s[i];

        }

        s[i] = x;//i = j的时候,将x填入中间位置  
        quick_sort(s, l, i - 1);//递归调用 
        quick_sort(s, i + 1, r);
    }
}
/*File:test.h*/
void quick_sort(int s[], int l, int r);

随便写一个快排的代码,2.然后构造一个swig module。

/* File:test.i*/
%module test

%{
#define SWIG_FILE_WITH_INIT
#include "test.h"
%}

void quick_sort(int s[], int l, int r);

3.终端输入(当前目录下,否则添加完整路径)
(C的情况下):

swig -python test.i

(C++的情况下)

swig -c++ -python test.i

会生成两个文件:test_wrap.c(c)或者test_wrap.cxx(c++)和test.py。当然这个.py是不可以直接使用的,还缺点东西。
我们把这里的c/c++文件叫做low-level,生成的py叫做high-level,对于c/c++的生成文件需要进行编译并链接其余的部分(文件中所引用的东西)创建一个扩展module,对于py文件,就是要导入的文件。

说下名字的问题。比如我们用的module:test.i就会默认生成一个加了_wrap的包装器test_wrap.c。如果要更改的话,可以使用swig的可选项-o指定。生成的py文件就是同名的.py文件。

4.然后我们继续后面的话题,如何使用它们。
先说一种方法:使用python的distutils库,这个东西玩自动化运维的人一定不陌生,当然也不准备详细说明,就是简单说一下。

from distutils.core import setup, Extension

test_module = Extension('_test',
sources=['test_wrap.c', 'test.c'],
)

setup (name = 'test',
version = '0.1',
author = "孟哲凡",
description = """swig demo""",
ext_modules = [test_module],
py_modules = ["test"],
)

从上面我们可以看到在test_module里的sources是目前已经有的,我们需要生成一个_test,然后放到setup函数里面,当然里面还可以放一些其他的东西,可以去看一下。它一般习惯就叫setup.py。

5.然后就可以了,终端执行

python setup.py build_ext --inplace

一般情况下会报错,说是缺少一个vcvarsall.bat的文件,这个东西是因为python的解释器底层是用了大量的c语言的,distutils也会用,它找不到,这是个VC里的东西,在python的lib里的_msvccompiler.py里面有说明版本位置这些。一种做法是按照这里的代码把VC装成指定版本,版本的计算方法是在终端输入python会提示 [MSC v.1900 64 bit (AMD64)]这种东西,这个1900就是版本号,前两个字节 - 6,后两个字节/10.0求和就是。所以1900就是13。可以下载vs2013就好了。但是通常情况下我们懒得这么做,因为很多情况下都是装过vs的,即便只装vc也麻烦,最简单的办法就是把_msvccompiler.py里的位置替换成你已有vs里的vcvarsall.bat目录位置。详细的做法百度里会有。简单说明一下。

当上面这个没有的问题的时候,我们正式开始,执行完会生成一个.pyd的文件,.pyd就是一个python引用其它语言的后缀,所以有了这个,之前生成.py文件才有完整的依赖,可以正式使用。

6.大概介绍到这里的时候,这篇文章就应该完了。但是细心的人会发现,好像不知道怎么用这个东西,因为我们的例子找的有点随意,里面有个数组,这个东西看似司空见惯。但是突然要用python做输入,有点晕,当我们用list或者tuple输入的时候都会报错,说是要求一个int []类型的参数,python里面哪有这种东西。但细心一想还是容易懂的,数组是什么,数组是指针的简单形式,也可以说c语言可以没有数组(图个方便),只有指针就够了。在swig的处理中,把python的函数和C的指针划分成一类。

我们刚才谈到了函数,所以尝试在python里面搞个函数,然后扔到里面,发现现在不会报类型错误了,但是会异常退出,因为我们不知道在函数里面返回点什么,他会认识。所以换个想法,如果我C里面有个函数可以用python调用,那C里面放什么我们该知道吧。搞块内存用就可以了,然后顺着再搞个赋值函数就可以了。所以开始去改一下module,加一个内联块:

%inline %{

int* array(int l) {
    return (int *)malloc(l * sizeof(int));
}

void array_set(int s[], int i, int v) {
    s[i] = v;
}

void print_array(int s[]) {
    for(int i = 0; i < 6; i++) {
        printf("%d\t",s[i]);
    }
}
%}

当然还要加一个free的函数,就不挂在上面了,这样当我们重新的在python里用一下发现就可以了,得到了正确的输出。

0   1   3   4   5   12  
Process finished with exit code 0

这部分就完了,后面说另一个办法:Linux里面用gcc编译,win下用vs里的功能生成链接库的办法。然后解释一下在这个过程中可能出现的一些错误。当这个都说完以后,就可以正经开始这个话题了。这些只是预热。因为c++有那么复杂的语法要用python去调用,要有很多的细节和方法。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,718评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,683评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,207评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,755评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,862评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,050评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,136评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,882评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,330评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,651评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,789评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,477评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,135评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,864评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,099评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,598评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,697评论 2 351