SWIG:numpy 包装器的意外结果?

Posted

技术标签:

【中文标题】SWIG:numpy 包装器的意外结果?【英文标题】:SWIG: Unexpected results with numpy wrappers? 【发布时间】:2017-06-19 11:17:17 【问题描述】:

不确定这是我的错误还是误解。非常感谢任何帮助。演示该问题的简明项目是 here

我正在包装一些 C++ 函数,这些函数采用指向缓冲区(8 位有符号或无符号)的指针和具有缓冲区长度的 int,通常遵循以下模式:some_function(char* buffer,int length)

采用示例 here 会根据以下内容生成一个外观合理的包装器:

example.i:

%module example

%
    #define SWIG_FILE_WITH_INIT
    #include "example.h"
%

// https://raw.githubusercontent.com/numpy/numpy/master/tools/swig/numpy.i
%include "numpy.i"

%init %
    import_array();
%

//
%apply (char* INPLACE_ARRAY1, int DIM1) (char* seq, int n)
%apply (unsigned char* INPLACE_ARRAY1, int DIM1) (unsigned char* seq, int n)
%apply (int* INPLACE_ARRAY1, int DIM1) (int* seq, int n)

// Include the header file with above prototypes
%include "example.h"

example.h:

// stubbed
double average_i(int* buffer,int bytes)

    return 0.0;

但是运行这个测试:

np_i = np.array([0, 2, 4, 6], dtype=np.int)
try:
    avg = example.average_i(np_i)
except Exception:
    traceback.print_exc(file=sys.stdout)
try:
    avg = example.average_i(np_i.data,np_i.size)
except Exception:
    traceback.print_exc(file=sys.stdout)

产生错误:

Traceback (most recent call last):
  File "test.py", line 13, in <module>
    avg = example.average_i(np_i)
TypeError: average_i expected 2 arguments, got 1
Traceback (most recent call last):
  File "test.py", line 17, in <module>
    avg = example.average_i(np_i.data,np_i.size)
TypeError: in method 'average_i', argument 1 of type 'int *'

第一个是有道理的,但与食谱中的示例相反。第二个虽然没有,average_i 的签名是 double average_i(int* buffer,int bytes)

我哪里错了? TAIA。

[更新1]

%apply 根据 Flexo 的建议更改了定义

// integer
%apply (int* INPLACE_ARRAY1,int DIM1) (int* buffer,int bytes)
// signed 8
%apply (char* INPLACE_ARRAY1,int DIM1) (char* buffer,int bytes)
// unsigned 8
%apply (unsigned char* INPLACE_ARRAY1,int DIM1) (unsigned char* buffer,int bytes)

函数 average_iaverage_u8 现在可以正常工作了。

但是 double average_s8(char* buffer,int bytes) 仍然失败并显示

Traceback (most recent call last):
  File "test.py", line 25, in <module>
    avg = example.average_s8(np_i8)
TypeError: average_s8 expected 2 arguments, got 1

【问题讨论】:

我真的不介意被否决,但有建设性吗?为什么这方面研究不足?说出你的理由! 【参考方案1】:

您的 %apply 指令错误,与您要包装的函数不匹配:

%apply (int* INPLACE_ARRAY1, int DIM1) (int* seq, int n)

这与您的函数average_i 不匹配,因为您提供的参数名称不同。更改您的 %apply to match SWIG 看到的声明,即:

%apply (int* INPLACE_ARRAY1, int DIM1) (int* buffer,int bytes)

【讨论】:

谢谢,非常感谢。奇怪的是,这解决了大约 66% 的问题,但不适用于普通的 char* 品种。我正在使用 SWIG 4.0.0 char* 往往有点特别,因为您也点击了字符串类型映射。 是时候让 SWIG 咬紧牙关开始使用 Clang ...感谢您的所有帮助。

以上是关于SWIG:numpy 包装器的意外结果?的主要内容,如果未能解决你的问题,请参考以下文章

在 Windows 中编译 SWIG python 包装器时,MinGW g++ 找不到 numpy\arrayobject.h

使用 SWIG 将 C++ <vector> 包装为 python NumPy 数组

如何使用 SWIG 在 C++ API 上生成 C 包装器? [复制]

带有 SWIG 未知长度数组的 NumPy C 扩展

将外部指针包装到 SWIG 数据结构中

SWIG 不接受指针参数的包装对象