SWIG + c + Python:传递和接收c数组 [英] SWIG+c+Python: Passing and receiving c arrays

查看:339
本文介绍了SWIG + c + Python:传递和接收c数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图重用一些旧的c代码与SWIG和Python。
现在我很困惑。我得到的错误可以通过一个小例子证明:



bsp.h:

 code> extern void add(int a [],int b [],int c []); 

bsp.c:

  #includebsp.h
void add(int a [],int b [],int c [])
{
c [0] [0] + b [0];
c [1] = a [1] + b [1];
}

bsp.i

 %module bsp 
%{
#includebsp.h;
%}
%includebsp.h;

setup.py:

 #!/ usr / bin / env python 

从distutils.core导入安装,扩展

bsp_module = Extension('_ bsp',
sources = ['bsp_wrap.c','bsp.c']


setup(name ='bsp',
ext_modules = [bsp_module],
py_modules = [bsp]

示例Python文件pybsp。 py:

  import bsp 

a = [1,1]
b = [1 ,1]
c = []

bsp.add(a,b,c)

print(c)



我得到错误:

  (最近调用最后):
文件pybsp.py,第31行,在< module>
bsp.add(a,b,c)
TypeError:在方法'add'中,类型为'int []'的参数1

现在,为什么我很困惑的是 SWIG文档说:
SWIG完全支持C / C ++指针。此外,SWIG在处理不完整类型信息时没有问题。



我也尝试添加

 %apply int * INPUT {int * a} 
% int * INPUT {int * b}
%apply int * OUTPUT {int * c}

到我的.i文件,这是在这个上下文中推荐,没有成功。
我的猜测是,我必须创建一个指针像对象在Python中传递,但我不知道如何工作,也希望,有一个更简单的方法。



非常感谢您的帮助!



PS:你可能猜到,这是我第一次与SWIG联系,不幸的是,无法从似乎相似的问题的解决方案中推导出解决方案。



编辑:
我发现,尺寸,如上所述,NumPy似乎是一个很好的选择,以避免手工包装。
基本示例在此处提供。因此,我更改了我的函数定义为

  void add(int * a,int dim_a,int * b,int dim_b,int * c,int dim_c)



现在包装器似乎有机会将NumPy数组转换为C数组。



i-File

 模块bsp 
%{
#define SWIG_FILE_WITH_INIT
#includebsp.h
%}

%includenumpy.i

%init%{
import_array();
%}

%apply(int * IN_ARRAY1,int DIM1){(int * a,int dim_a),(int * b,int dim_b)}
%apply int * ARGOUT_ARRAY1,int DIM1){(int * c,int dim_c)}

%includebsp.h

setup.py

 #!/ usr / bin / env python 

从distutils.core导入安装,扩展
import numpy

try:
numpy_include = numpy.get_include()
except AttributeError:
numpy_include = numpy.get_numpy_include()

bsp_module = Extension('_ bsp',
sources = ['bsp_wrap.c','bsp.c'] ,
include_dirs = [numpy_include]


setup(name ='bsp',
ext_modules = [bsp_module],
py_modules = [_ bsp ]

最后是python脚本,我想使用int32类型转换错误(int64 - > int32)来自NumPy

  import bsp 
import numpy as np
a = np.array([1,1],dtype = np.int32)
b = np.array([1,1],dtype = np.int32)
c = np.array([1, 1],dtype = np.int32)

bsp.add(a,b,c)

print(c)



现在我摆脱了前一个错误,但是我有了一个新的错误:

 文件pybsp.py,第10行,在< module> 
bsp.add(a,b,c)
TypeError:Int dimension expected。 '未知类型'给定。

有任何建议吗?

解决方案

好吧,现在我有了。正如在上面的EDIT中所写的,使用numpy.i可以很容易地包装数组。我没有看到的是,ARGOUT数组不想要一个数组作为输入,如在C.只有所需的维度。因此,使用上面的代码,脚本

  import bsp 
import numpy as np
a = np。 array([1,1],dtype = np.int32)
b = np.array([1,1],dtype = np.int32)

c = bsp.add(a, b,np.shape(a)[0])

print(c)

提供所需的输出

  [2 2] 


I am trying to reuse some old c code with SWIG and Python. Right now I am quite confused. The errors I get can be demonstrated on a small example:

bsp.h:

extern void add(int a[], int b[], int c[]);

bsp.c:

#include "bsp.h" 
void add(int a[], int b[], int c[]) 
{ 
    c[0] = a[0] + b[0]; 
    c[1] = a[1] + b[1]; 
}

bsp.i

%module bsp
%{
    #include "bsp.h";
%}
%include "bsp.h";

setup.py:

#!/usr/bin/env python

from distutils.core import setup, Extension

bsp_module = Extension('_bsp',
    sources = ['bsp_wrap.c', 'bsp.c']
)

setup(name = 'bsp',
    ext_modules = [bsp_module],
    py_modules = ["bsp"]
)

The example Python file "pybsp.py":

import bsp

a = [1, 1]
b = [1, 1]
c = []

bsp.add(a, b, c)

print(c)

And I get the error:

Traceback (most recent call last):
    File "pybsp.py", line 31, in <module>
    bsp.add(a, b, c)
TypeError: in method 'add', argument 1 of type 'int []'

Now, why I am confused is that the SWIG Documentation says: "C/C++ pointers are fully supported by SWIG. Furthermore, SWIG has no problem working with incomplete type information."

I also tried to add

%apply int * INPUT { int *a}
%apply int * INPUT { int *b}
%apply int * OUTPUT { int *c}

to my .i file, which was recommended in this context, without success. My guess is, that I have to create a pointer like object in Python to pass, but I don't know how that works and also hope, that there is a simpler way.

Thank you very much for your help!

P.S.: As you might guess, this is my first contact with SWIG, so, unfortunately, I was not able to deduce the solution from solutions of seemingly similar problems.

EDIT: I found out that for arrays with given dimensions, as above, NumPy seems to be a good option to avoid the wrapping by hand. Basic examples are given here. Accordingly I changed my function definition to

void add(int* a, int dim_a, int *b, int dim_b, int *c, int dim_c)

Now the wrapper seems to have a chance to convert the NumPy array into a C array.

i-File

%module bsp
%{
    #define SWIG_FILE_WITH_INIT
    #include "bsp.h"
%}

%include "numpy.i"

%init %{
    import_array();
%}

%apply (int* IN_ARRAY1, int DIM1){(int* a, int dim_a), (int* b, int dim_b)}
%apply (int* ARGOUT_ARRAY1, int DIM1){(int* c, int dim_c)}

%include "bsp.h"

setup.py

#!/usr/bin/env python

from distutils.core import setup, Extension
import numpy

try:
        numpy_include = numpy.get_include()
except AttributeError:
        numpy_include = numpy.get_numpy_include()

bsp_module = Extension('_bsp',
                       sources=['bsp_wrap.c', 'bsp.c'],
                       include_dirs=[numpy_include]
                       )

setup(name='bsp',
      ext_modules=[bsp_module],
      py_modules=["_bsp"]
      )

And finally the python script, where I wanted to use int32 to avoid a type conversion Error (int64 -> int32) from NumPy

import bsp
import numpy as np
a = np.array([1, 1], dtype=np.int32)
b = np.array([1, 1], dtype=np.int32)
c = np.array([1, 1], dtype=np.int32)

bsp.add(a, b, c)

print(c)

Now I got rid of the previous Error, but I have a new one:

  File "pybsp.py", line 10, in <module>
    bsp.add(a, b, c)
TypeError: Int dimension expected.  'unknown type' given.

Any suggestions?

解决方案

Alright, now I have it. As written in the EDIT above, with numpy.i the arrays can be wrapped quite comfortably. What I did not see was, that the ARGOUT Array does not want an array as Input, as in C. There is just the dimension needed. So, with the Code above, the Script

import bsp
import numpy as np
a = np.array([1, 1], dtype=np.int32)
b = np.array([1, 1], dtype=np.int32)

c = bsp.add(a, b, np.shape(a)[0])

print(c)

Gives the desired Output

[2 2]

这篇关于SWIG + c + Python:传递和接收c数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆