带有 SWIG 的 C++ 数组到 Numpy 的 TypeError 问题

Posted

技术标签:

【中文标题】带有 SWIG 的 C++ 数组到 Numpy 的 TypeError 问题【英文标题】:C++ Array to Numpy with SWIG Problem with TypeError 【发布时间】:2018-09-06 07:49:17 【问题描述】:

我正在研究在 Python 中调用 C++ 库的 SWIG。一个问题是,当我在 C++ 中使用一维数组并想在 Python 中将其称为 Numpy 数组时,我得到了错误。

头文件:example.h

#include <iostream>
using namespace std;
class Example 
  public:
  void say_hello();
  void add(int x, int y, int *result);
  int sub(int *x, int *y);
  void array_add(int *a, int *b, int *c);
;

C++ 文件:example.cpp

#include "example.h"

void Example::say_hello() 
    cout<<"Hello Example."<<endl;


void Example::add(int x, int y, int *result) 
    *result = x + y;


int Example::sub(int *x, int *y) 
    return *x-*y;



void Example::array_add(int *a, int *b, int *c)  
    c[0] = a[0] + b[0]; 
    c[1] = a[1] + b[1]; 

SWIG 接口文件:example.i

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

%include "typemaps.i"
%include "numpy.i"
%init %
   import_array();
%

%apply int *OUTPUT  int *result ;
%apply int *INPUT  int *x, int *y;

%apply int *INPLACE_ARRAY1 int *a, int *b, int *c;

%include "example.h"

安装文件:setup.py

#!/usr/bin/env python

from distutils.core import setup, Extension
import numpy
import os

example_module = Extension('_example',
    sources=['example.cpp', 'example_wrap.cxx',],
)
setup (
    name = 'example',
    version = '0.1',
    author = "Frank Tang",
    description = """Simple swig C\+\+/Python example""",
    ext_modules = [example_module],
    py_modules = ["example"],
)

文件:test_example.py test_example.py

运行“python test_example.py”后,我收到如下错误消息。我使用 macOS。

(virtualenv) bogon:source tangsg$ python test_example.py 
Hello Example.
7
3
Traceback (most recent call last):
  File "test_example.py", line 18, in <module>
    example.Example().array_add(a, b, c)
  File "/Users/tangsg/Projects/test/source/example.py", line 115, in 
array_add
    return _example.Example_array_add(self, a, b, c)
TypeError: in method 'Example_array_add', argument 2 of type 'int *'
(virtualenv) bogon:source tangsg$ ›

Error message

【问题讨论】:

请编辑您的问题并以文本形式添加错误消息,而不是图像 以文本形式添加错误消息 array_add 如何知道这些数组的长度? 【参考方案1】:

您的类型映射和array_add 函数的声明无效。 NumPy 数组总是有一个大小,这必须传达给 C++。 NumPy with SWIG 的用法有相当广泛的文档。

另外两件事:

addsub 的函数签名效率低下。而不是使用笨拙的指针参数,只需按值调用并返回一个值,即

  int add(int x, int y)  return x + y; 
  int sub(int x, int y)  return x - y; 

那么你也可以从接口文件中删除%apply int *OUTPUT int *result ;%apply int *INPUT int *x, int *y;

永远不要在头文件中使用using namespace std;! (Why is "using namespace std;" considered bad practice?)


example.h

#include <algorithm>
#include <iostream>

class Example 
public:
    void array_add(int *a, int len_a, int *b, int len_b, int *c, int len_c) 
        int const end = std::min(len_a, std::min(len_b, len_c));
        for (int i = 0; i < end; ++i) 
            c[i] = a[i] + b[i];
        
    
;

example.i

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

%include "numpy.i"
%init %
   import_array();
%

%apply (int *IN_ARRAY1, int DIM1)  (int *a, int len_a), (int *b, int len_b) ;
%apply (int *INPLACE_ARRAY1, int DIM1)  (int *c, int len_c) ;

%include "example.h"

test.py

import example
import numpy as np
E = example.Example()
a = np.array([1,1], dtype=np.int32)
b = np.array([1,1], dtype=np.int32)
c = np.array([1,1], dtype=np.int32)
E.array_add(a,b,c)
print(c)

调用示例:

$ swig -python -c++ example.i
$ clang++ -Wall -Wextra -Wpedantic -I/usr/include/python2.7 -fPIC -shared example_wrap.cxx -o _example.so -lpython2.7
$ python test.py
[2 2]

【讨论】:

现在工作。谢谢。

以上是关于带有 SWIG 的 C++ 数组到 Numpy 的 TypeError 问题的主要内容,如果未能解决你的问题,请参考以下文章

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

使用 swig 使 C++ 类看起来像一个 numpy 数组

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

使用 SWIG 的几个 numpy 数组

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

如何使用 SWIG 将 C++ 数组转换为 Python 列表?