C++ Array to Numpy with SWIG Problem with TypeError
C++ Array to Numpy with SWIG Problem with TypeError
我正在研究 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
函数的声明无效。 NumPy 数组总是有一个大小,这必须与 C++ 通信。 NumPy with SWIG.
的使用有相当广泛的文档
另外两件事:
add
和 sub
的函数签名效率低下。与其使用笨拙的指针参数,不如按值调用 return 一个值,即
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]
我正在研究 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
函数的声明无效。 NumPy 数组总是有一个大小,这必须与 C++ 通信。 NumPy with SWIG.
另外两件事:
add
和sub
的函数签名效率低下。与其使用笨拙的指针参数,不如按值调用 return 一个值,即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]