C ++ Array to Numpy с SWIG Проблема с TypeError - PullRequest
0 голосов
/ 06 сентября 2018

Я изучаю SWIG для вызова библиотек C ++ в Python. Одна проблема заключается в том, что когда я использую одномерный массив в C ++ и хочу назвать его в Python как Numpy arrary, я получил ошибку.

Заголовочный файл: 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$ ›

Сообщение об ошибке

1 Ответ

0 голосов
/ 07 сентября 2018

Ваши карты типов и ваше объявление функции array_add недопустимы. Массивы NumPy всегда имеют размер, и это должно быть передано в C ++. Для использования NumPy с SWIG .

имеется довольно обширная документация.

Две другие вещи:

  • Сигнатуры функций add и sub неэффективны. Вместо использования неуклюжих аргументов указателя, просто вызовите по значению и верните значение, т.е.

    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; в заголовочном файле! ( Почему "использование пространства имен std" считается плохой практикой? )


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 max = std::max(len_a, std::max(len_b, len_c));
        for (int i = 0; i < max; ++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]
...