swig,传递没有指定尺寸的 carrays
swig, pass carrays with no dimension especified
这是我要包装的部分代码:
typedef unsigned char UINT8;
...
void fn(UINT8 data[]);
在 .i 文件中,我包括:
From 8.2.2 carrays.i:
%array_class(UINT8, UINT8Array)
支持数组写操作:
%typemap(in) UINT8[ANY] (_basetype temp[_dim0]) {
int i;
if (!PySequence_Check($input)) {
PyErr_SetString(PyExc_ValueError,"Expected a sequence as input");
return NULL;
}
if (PySequence_Length($input) != _dim0) {
PyErr_SetString(PyExc_ValueError,"Input sequence size incorrect, should have _dim0 ints");
return NULL;
}
for (i = 0; i < _dim0; i++) {
PyObject *o = PySequence_GetItem($input,i);
if (PyNumber_Check(o)) {
temp[i] = (_basetype)PyInt_AsLong(o);
Py_DECREF(o);
} else {
Py_XDECREF(o);
PyErr_SetString(PyExc_ValueError,"Input sequence elements must be numbers");
return NULL;
}
}
= temp;
}
然后,在编译时,我的代码失败了:
example_wrap.cxx:40:15: error: storage size of ‘temp2’ isn’t known
UINT8 temp2[] ;
请注意,如果我的函数类似于:
,则包装有效
void fn(UINT8 数据[10]);
void fn(UINT8* 数据);
有什么方法可以告诉 swig,当有一个 UINT8[] 来表征它时,因为它是一个 UINT8 *。像这样:
%typemap(in) UINT8[] (_basetype *temp) {
谢谢,
巴勃罗
OP 在评论中声明函数参数具有固定大小。假设头文件如下所示:
#ifdef _WIN32
# define API __declspec(dllexport)
#else
# define API
#endif
typedef unsigned char UINT8;
API void fn(UINT8 data[]); // data must be length 300
OP 的类型图有效,但不知道大小。要让 SWIG 知道有一个固定大小并仍然利用通用类型映射,可以使用以下内容:
%module test
%{
#include "test.h"
// Implementation...this would normally be in a .cpp file and linked in.
// Note to see the result an argout typemap would be needed too...
API void fn(UINT8 data[]) {
for(int i = 0; i < 300; ++i)
data[i] += 1;
}
%}
// OP's original generalized array typemap...
%typemap(in) UINT8[ANY] (_basetype temp[_dim0]) {
int i;
if (!PySequence_Check($input)) {
PyErr_SetString(PyExc_ValueError,"Expected a sequence as input");
return NULL;
}
if (PySequence_Length($input) != _dim0) {
PyErr_SetString(PyExc_ValueError,"Input sequence size incorrect, should have _dim0 ints");
return NULL;
}
for (i = 0; i < _dim0; i++) {
PyObject *o = PySequence_GetItem($input,i);
if (PyNumber_Check(o)) {
temp[i] = (_basetype)PyInt_AsLong(o);
Py_DECREF(o);
} else {
Py_XDECREF(o);
PyErr_SetString(PyExc_ValueError,"Input sequence elements must be numbers");
return NULL;
}
}
= temp;
}
// Assume there are lots of other functions in test.h,
// but we don't want to wrap the function that requires
// a fixed-sized array and doesn't declare the size.
%ignore fn;
// Process test.h, but skip wrapping fn.
%include "test.h"
// This "un-ignores" the function and provides a replacement
// that declares the fixed size.
// See http://www.swig.org/Doc3.0/SWIGDocumentation.html#SWIG_rename_ignore
%rename("%s") fn;
void fn(UINT8 temp[300]);
演示:
>>> import test
>>> test.fn([1,2,3])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: Input sequence size incorrect, should have 300 ints
>>> test.fn([1]*300) # This works
>>> test.fn('a'*300)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: Input sequence elements must be numbers
这是我要包装的部分代码:
typedef unsigned char UINT8;
...
void fn(UINT8 data[]);
在 .i 文件中,我包括:
From 8.2.2 carrays.i:
%array_class(UINT8, UINT8Array)
支持数组写操作:
%typemap(in) UINT8[ANY] (_basetype temp[_dim0]) {
int i;
if (!PySequence_Check($input)) {
PyErr_SetString(PyExc_ValueError,"Expected a sequence as input");
return NULL;
}
if (PySequence_Length($input) != _dim0) {
PyErr_SetString(PyExc_ValueError,"Input sequence size incorrect, should have _dim0 ints");
return NULL;
}
for (i = 0; i < _dim0; i++) {
PyObject *o = PySequence_GetItem($input,i);
if (PyNumber_Check(o)) {
temp[i] = (_basetype)PyInt_AsLong(o);
Py_DECREF(o);
} else {
Py_XDECREF(o);
PyErr_SetString(PyExc_ValueError,"Input sequence elements must be numbers");
return NULL;
}
}
= temp;
}
然后,在编译时,我的代码失败了:
example_wrap.cxx:40:15: error: storage size of ‘temp2’ isn’t known
UINT8 temp2[] ;
请注意,如果我的函数类似于:
,则包装有效void fn(UINT8 数据[10]);
void fn(UINT8* 数据);
有什么方法可以告诉 swig,当有一个 UINT8[] 来表征它时,因为它是一个 UINT8 *。像这样:
%typemap(in) UINT8[] (_basetype *temp) {
谢谢, 巴勃罗
OP 在评论中声明函数参数具有固定大小。假设头文件如下所示:
#ifdef _WIN32
# define API __declspec(dllexport)
#else
# define API
#endif
typedef unsigned char UINT8;
API void fn(UINT8 data[]); // data must be length 300
OP 的类型图有效,但不知道大小。要让 SWIG 知道有一个固定大小并仍然利用通用类型映射,可以使用以下内容:
%module test
%{
#include "test.h"
// Implementation...this would normally be in a .cpp file and linked in.
// Note to see the result an argout typemap would be needed too...
API void fn(UINT8 data[]) {
for(int i = 0; i < 300; ++i)
data[i] += 1;
}
%}
// OP's original generalized array typemap...
%typemap(in) UINT8[ANY] (_basetype temp[_dim0]) {
int i;
if (!PySequence_Check($input)) {
PyErr_SetString(PyExc_ValueError,"Expected a sequence as input");
return NULL;
}
if (PySequence_Length($input) != _dim0) {
PyErr_SetString(PyExc_ValueError,"Input sequence size incorrect, should have _dim0 ints");
return NULL;
}
for (i = 0; i < _dim0; i++) {
PyObject *o = PySequence_GetItem($input,i);
if (PyNumber_Check(o)) {
temp[i] = (_basetype)PyInt_AsLong(o);
Py_DECREF(o);
} else {
Py_XDECREF(o);
PyErr_SetString(PyExc_ValueError,"Input sequence elements must be numbers");
return NULL;
}
}
= temp;
}
// Assume there are lots of other functions in test.h,
// but we don't want to wrap the function that requires
// a fixed-sized array and doesn't declare the size.
%ignore fn;
// Process test.h, but skip wrapping fn.
%include "test.h"
// This "un-ignores" the function and provides a replacement
// that declares the fixed size.
// See http://www.swig.org/Doc3.0/SWIGDocumentation.html#SWIG_rename_ignore
%rename("%s") fn;
void fn(UINT8 temp[300]);
演示:
>>> import test
>>> test.fn([1,2,3])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: Input sequence size incorrect, should have 300 ints
>>> test.fn([1]*300) # This works
>>> test.fn('a'*300)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: Input sequence elements must be numbers