python数组 swig_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去调用,要有很多的细节和方法。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值