如何将复数从 python numpy 传递给 c(目前正在尝试使用 SWIG)

Posted

技术标签:

【中文标题】如何将复数从 python numpy 传递给 c(目前正在尝试使用 SWIG)【英文标题】:How to pass complex numbers from python numpy to c (trying to use SWIG at the moment) 【发布时间】:2012-08-09 08:15:23 【问题描述】:

我想在 python 中调用具有复杂编号输入的 c 编写函数。我尝试使用 SWIG 生成包装器 - 但它似乎失败了。我认为我需要制定在 numpy.i 中使用的正确“宏” - 但不确定它是什么 - 任何人都有这方面的经验 - 或者我可以通过其他方式解决这个问题?

numpy.i 显示在底部 - 尽管它已被注释掉。我尝试使用这些宏 - 但它们失败了,SWIG 抱怨我尝试的以下宏扩展的语法错误:

%numpy_typemaps(complex float, NPY_CFLOAT , int)
%numpy_typemaps(complex double, NPY_CDOUBLE, int)
%numpy_typemaps(complex long double, NPY_CLONGDOUBLE, int)

这些是我的文件:

ComplexNumbers.c

# include <math.h>
# include <complex.h>


double complex returnX(double complex X) 
/*
    fresnel reflection coefficient rs
*/

    return X;

ComplexNumbers.i:

%
#define SWIG_FILE_WITH_INIT
%
%include "numpy.i"
%init %
import_array();
%


%module ComplexNumbers

%inline %
extern double complex returnX(double complex X);
%

Python:

#!/usr/bin/env python

"""
setup.py file for ComplexNumbers
"""

from distutils.core import setup
from distutils.extension import Extension

import numpy


ComplexNumbers_module = Extension('_ComplexNumbers',
                           sources=['ComplexNumbers_wrap.c', 
                                    'ComplexNumbers.c'],
                           include_dirs=[numpy.get_include()]
                           )

setup (name = 'ComplexNumbers',
       version = '1.0',
       author      = "JP Hadden jp.hadden@bristol.ac.uk",
       description = """Spectral Interfereometry functions""",
       ext_modules = [ComplexNumbers_module],
       py_modules = ["ComplexNumbers"],
       )

编译器的错误输出

C:\MinGW32-xy\bin\gcc.exe -mno-cygwin -mdll -O -Wall -IC:\Python27\lib\site-pack
ages\numpy\core\include -IC:\Python27\include -IC:\Python27\PC -c ComplexNumbers
_wrap.c -o build\temp.win32-2.7\Release\complexnumbers_wrap.o
ComplexNumbers_wrap.c:2975:23: error: expected '=', ',', ';', 'asm' or '__attrib
ute__' before 'returnX'
ComplexNumbers_wrap.c: In function '_wrap_returnX':
ComplexNumbers_wrap.c:2982:18: error: expected '=', ',', ';', 'asm' or '__attrib
ute__' before 'arg1'
ComplexNumbers_wrap.c:2982:18: error: 'arg1' undeclared (first use in this funct
ion)
ComplexNumbers_wrap.c:2982:18: note: each undeclared identifier is reported only
 once for each function it appears in
ComplexNumbers_wrap.c:2986:18: error: expected '=', ',', ';', 'asm' or '__attrib
ute__' before 'result'
ComplexNumbers_wrap.c:2986:18: error: 'result' undeclared (first use in this fun
ction)
ComplexNumbers_wrap.c:2997:24: error: expected ')' before 'complex'
ComplexNumbers_wrap.c:2997:24: error: pointer value used where a floating point
value was expected
ComplexNumbers_wrap.c:2997:14: error: invalid type argument of unary '*' (have '
double')
ComplexNumbers_wrap.c:3000:20: error: expected ')' before 'complex'
ComplexNumbers_wrap.c:3000:20: warning: implicit declaration of function 'return
X'
ComplexNumbers_wrap.c:3001:15: error: expected ')' before 'complex'
ComplexNumbers_wrap.c:3001:15: error: expected ')' before 'complex'
ComplexNumbers_wrap.c:3001:15: error: expected ')' before 'complex'
ComplexNumbers_wrap.c:3001:15: error: pointer value used where a floating point
value was expected
ComplexNumbers_wrap.c:3001:15: error: expected ')' before 'complex'
ComplexNumbers_wrap.c:3001:15: error: incompatible type for argument 1 of 'memcp
y'
c:\mingw32-xy\bin\../lib/gcc/mingw32/4.5.2/../../../../include/string.h:38:40: n
ote: expected 'void *' but argument is of type 'double'
error: command 'gcc' failed with exit status 1

【问题讨论】:

编译器的输出看起来好像您没有明确启用 C99 模式 - 我认为默认值是(仍然)gnu89。编译器上的-std=c99 调用是否清楚一些? 你拥有的 %inline 也很复杂 - 如果你有这样的头文件,你可以只使用 double complex returnX(double complex X); 而不是 %inline 或只使用 %include "ComplexNumbers.h" 【参考方案1】:

我不确定它如何与 Numpy 交互,但 SWIG 肯定包含对 C99 复杂类型的支持。我可以通过以下示例验证这一点:

%module test
%
#include <complex.h>
%

%include <complex.i>

%inline %
  double complex test(double complex X) 
    return X;
  
%

这使用 SWIG complex.i 接口。

(注意这里%inline 用于在一个地方声明、定义和包装所有内容 - 便于测试,但对于“真实”代码我倾向于使用%include)。

我编译了这个(在 Linux 上):

swig -Wall -python test.i 
gcc -std=c99 -Wall -Wextra test_wrap.c -I/usr/include/python2.7 -shared -o _test.so

只有一个警告就可以很好地构建。一旦完成,我就可以这样做:

LD_LIBRARY_PATH=.  python                       
Python 2.7.3 (default, Aug  1 2012, 05:16:07) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import test
>>> test.test(complex(0,1))
1j
>>> test.test(complex(0,2))
2j
>>> test.test(complex(1,2))
(1+2j)
>>> 

这似乎是接受并返回原生 Python 复杂类型。

我还可以编译以下界面:

%
#define SWIG_FILE_WITH_INIT
#include <complex.h>
%
%include <complex.i>
%include <numpy.i>
%init %
import_array();
%

%numpy_typemaps(complex float, NPY_CFLOAT , int)
%numpy_typemaps(complex double, NPY_CDOUBLE, int)
%numpy_typemaps(complex long double, NPY_CLONGDOUBLE, int)

%module test

%inline %
  double complex test(double complex X) 
    return X;
  
%

在编译器标志中添加了%include &lt;complex.i&gt;-std=c99。我认为您可以使用类似these options 的方式让 distutils 为您设置。

【讨论】:

感谢您的帮助......设法让我的代码现在工作。对于那些感兴趣的人......重要的是我不确定编译器标志有什么影响 - 但它适用于复杂的 include % #include % %include

以上是关于如何将复数从 python numpy 传递给 c(目前正在尝试使用 SWIG)的主要内容,如果未能解决你的问题,请参考以下文章

将二维 C 数组传递给 python numpy

使用 SWIG 将 numpy 数组元素(int)传递给 c++ int

如何使用 ctypes 将 numpy ndarrays 传递给 c++ 函数?

如何将数组从 C 传递到嵌入式 python 脚本

SWIG:将 2d numpy 数组传递给 C 函数 f(double a[])

如何将2D数组作为参数从C#传递给python