【发布时间】:2019-04-24 04:06:41
【问题描述】:
我有一个使用字符串输出参数的 C API。 (为了保护无辜者,实际签名已更改。这是一个简单的例子。)
void func( char* buf, size_t buflen, char* buf2, size_t buf2len );
buf 和buflen 是有效的输出参数,其中buflen 和buf2len 是这些缓冲区(已经)分配的大小。
在调用代码中,我不想传入任何参数。相反,我希望返回字符串。
result1,result2 = func()
我不希望将缓冲区/大小传递给包装器函数,而是让它由包装器分配,转换为 Python 字符串,并在返回 Python 字符串之前解除分配。
我看到的大多数与此相关的cstring.i 类型映射都要求我为包装函数提供一个字符串。分配类型映射都需要char**。
我正在寻找类似于使用 OUTPUT 作为外参数名称的行为,但缓冲区/大小对是(单个)外参数。
我无权更改 API。我只是想让它易于使用。
是否已经有一个用于此的类型映射,或者你能帮我构建一个吗?
试用 1(仅限 Python)
我得到了这个功能(没有测试性能或内存使用情况)。
%typemap(in,numinputs=0)(char* mutable_buffer, size_t mutable_buffer_size) {
$1 = malloc(sizeof(char)*4096);
$1[0] = 0x0;
$2 = 4096;
}
%typemap(argout)(char* mutable_buffer, size_t mutable_buffer_size) {
#ifdef SWIGPYTHON
PyObject *o;
$1[4095] = 0x0; // null-terminate it, just in case
o = PyUnicode_FromString($1);
resultobj = SWIG_Python_AppendOutput(resultobj,o);
#endif
}
%typemap(freearg)(char* mutable_buffer, size_t mutable_buffer_size) {
free($1);
}
我更愿意在不求助于特定语言的修复的情况下解决这个问题。
【问题讨论】:
-
如果你想要一个输出,它必须是
char**,否则你不能修改指针。 -
@JensMunk 如果你传入一个先前分配的
char*和一个size_t表明它有多大,函数可以在不分配它的情况下向它写入数据。 -
你是对的,但这也是一个输入 - 一种处理输出的非常烦人的方式。如果以这种方式处理输出,则提供一个返回整数的函数是有意义的,这是用户在调用 func 之前需要分配的大小
-
在这种情况下,作为包装维护者,我可以知道一些合理的界限来放置在字符串上。从客户端的角度来看(尤其是在脚本语言中),他们不想欺骗字符串大小等。如果我知道所有内容总是适合 4096 字节,那么客户端不需要告诉我如何可能很大,我可以返回一个字符串。
-
在这种情况下,有很多选择。您可以包含
%include "carrays.i"和%array_class(char, charArray).. 使用carr = lib.charArray(4096)分配一个 char 数组,然后简单地将其作为参数传递。