如何将 SWIG 类型映射_仅_应用于特定函数?
How do I apply a SWIG typemap to _only_ a specific function?
假设我有一个函数,我想为其应用一个特殊的类型映射(因为它return将二进制数据作为字符数组)。
const char* returnBinaryData( int arg1, int arg2, size_t ret_length );
因为还有其他具有相同 return 类型的函数,我 不想 触摸。
const char* getName( int arg1, int arg2 );
有没有办法将 (out
) 类型映射仅应用于特定函数(使用其名称,而不是其参数列表)?
(我将 SWIG 与 Python 一起使用。)
更新:针对 类
其中一个复杂因素是我要包装的函数是一个 class 方法。
将此视为定义。
class A {
public:
char datum[16];
char name[32];
A( int32_t seed ) : name("sample name") {
for (int i=0;i<16;i++) datum[i] = static_cast<char>(((i*i+seed) % 64) + '0');
}
const char* getName() {
return name;
}
const char* getBinaryData( int32_t arg1, int32_t length ) {
auto s = new char[length];
for (int i=0;i<length;i++) s[i] = datum[(arg1 + i) % sizeof(datum)];
return s;
}
};
需要更改什么才能“重命名”包装器以将其用作 class 方法?
我尝试确定重命名操作的范围,但它生成的包装代码没有达到我的要求。 (AFAICT,文档并不完全清楚这样做。)
我使用了包装函数并为特殊情况创建了自定义类型映射:
test.i
%module test
%{
const char* getName(int arg1, int arg2) {
static char s[] {"something"};
return s;
}
const char* returnBinaryData(int arg1, int arg2, size_t ret_length) {
auto s = new char[ret_length];
for(size_t i = 0; i < ret_length; ++i)
s[i] = static_cast<char>(i % 256);
return s;
}
// wrapper to allow custom typemap
void mygetbin(int arg1, int arg2, size_t length, const char** output) {
*output = returnBinaryData(arg1, arg2, length);
}
%}
%include <exception.i>
// Input typemap that expects a Python integer input for this precise pair of parameters
%typemap(in) (size_t length, const char** output) (char* out = nullptr) %{
= &out;
if(!PyLong_Check($input))
SWIG_exception(SWIG_TypeError, "expected integer");
= PyLong_AsUnsignedLongLong($input);
%}
// A Python bytes object will be returned that Python will manage,
// so free the C++ allocation to prevent a memory leak.
%typemap(freearg) (size_t length, const char** output) %{
delete[] *;
%}
// Append the output argument to the return value.
%typemap(argout) (size_t length, const char** output) %{
$result = SWIG_Python_AppendOutput($result, PyBytes_FromStringAndSize(*, ));
%}
%ignore returnBinaryData; // necessary if getName and returnBinaryData included via %include "someheader.h"
// Process this function normally with default handling of char* output.
// This could be %include "someheader.h" instead, and all the functions would be swigged except
// for the ignored function.
const char* getName(int arg1, int arg2);
// Explicitly rename the wrapper and process it.
%rename(returnBinaryData) mygetbin;
void mygetbin(int arg1, int arg2, size_t length, const char** output);
演示:
>>> import test
>>> test.getName(1,2)
'something'
>>> test.returnBinaryData(1,2,10)
b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t'
假设我有一个函数,我想为其应用一个特殊的类型映射(因为它return将二进制数据作为字符数组)。
const char* returnBinaryData( int arg1, int arg2, size_t ret_length );
因为还有其他具有相同 return 类型的函数,我 不想 触摸。
const char* getName( int arg1, int arg2 );
有没有办法将 (out
) 类型映射仅应用于特定函数(使用其名称,而不是其参数列表)?
(我将 SWIG 与 Python 一起使用。)
更新:针对 类
其中一个复杂因素是我要包装的函数是一个 class 方法。
将此视为定义。
class A {
public:
char datum[16];
char name[32];
A( int32_t seed ) : name("sample name") {
for (int i=0;i<16;i++) datum[i] = static_cast<char>(((i*i+seed) % 64) + '0');
}
const char* getName() {
return name;
}
const char* getBinaryData( int32_t arg1, int32_t length ) {
auto s = new char[length];
for (int i=0;i<length;i++) s[i] = datum[(arg1 + i) % sizeof(datum)];
return s;
}
};
需要更改什么才能“重命名”包装器以将其用作 class 方法?
我尝试确定重命名操作的范围,但它生成的包装代码没有达到我的要求。 (AFAICT,文档并不完全清楚这样做。)
我使用了包装函数并为特殊情况创建了自定义类型映射:
test.i
%module test
%{
const char* getName(int arg1, int arg2) {
static char s[] {"something"};
return s;
}
const char* returnBinaryData(int arg1, int arg2, size_t ret_length) {
auto s = new char[ret_length];
for(size_t i = 0; i < ret_length; ++i)
s[i] = static_cast<char>(i % 256);
return s;
}
// wrapper to allow custom typemap
void mygetbin(int arg1, int arg2, size_t length, const char** output) {
*output = returnBinaryData(arg1, arg2, length);
}
%}
%include <exception.i>
// Input typemap that expects a Python integer input for this precise pair of parameters
%typemap(in) (size_t length, const char** output) (char* out = nullptr) %{
= &out;
if(!PyLong_Check($input))
SWIG_exception(SWIG_TypeError, "expected integer");
= PyLong_AsUnsignedLongLong($input);
%}
// A Python bytes object will be returned that Python will manage,
// so free the C++ allocation to prevent a memory leak.
%typemap(freearg) (size_t length, const char** output) %{
delete[] *;
%}
// Append the output argument to the return value.
%typemap(argout) (size_t length, const char** output) %{
$result = SWIG_Python_AppendOutput($result, PyBytes_FromStringAndSize(*, ));
%}
%ignore returnBinaryData; // necessary if getName and returnBinaryData included via %include "someheader.h"
// Process this function normally with default handling of char* output.
// This could be %include "someheader.h" instead, and all the functions would be swigged except
// for the ignored function.
const char* getName(int arg1, int arg2);
// Explicitly rename the wrapper and process it.
%rename(returnBinaryData) mygetbin;
void mygetbin(int arg1, int arg2, size_t length, const char** output);
演示:
>>> import test
>>> test.getName(1,2)
'something'
>>> test.returnBinaryData(1,2,10)
b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t'