我有以下方法,我使用 SWIG 包装以在 Python 中访问它:
void some_class::some_method( FILE *fp, int *pT, int **pO ) {
fscanf( fp, "lalala", pT );
如何为第一个参数传递 StringIO ?我应该使用什么类型图?
简单的解决方案是构建一个类型映射,用于fmemopen
自动FILE*
为您创建一个。我创建了一个示例:
%module test
%include <typemaps.i>
%typemap(in) FILE *sb (PyObject *str=NULL) {
str = PyObject_CallMethod($input, "getvalue", NULL);
char *buf = NULL;
int len = 0;
PyString_AsStringAndSize(str, &buf, &len);
$1 = fmemopen(buf, len, "r");
}
%typemap(freearg) FILE *sb {
if ($1) fclose($1);
Py_XDECREF(str$argnum);
}
%apply int *OUTPUT { int * i };
%inline %{
void foo(FILE *sb, int *i) {
fscanf(sb, "%d", i);
}
%}
这有两个部分,首先有一些 python C API 可以调用getvalue
,StringIO
以便访问它保存的数据。这个缓冲区需要至少和 一样长FILE*
,所以我们必须引入一个额外的变量并在完成后清理它。
我也曾经%apply
自动将int *i
其视为输出而不是输入。这可能足以做你想做的事情。
这足以让我运行以下测试程序:
import StringIO
import test
buf=StringIO.StringIO("666")
print test.foo(buf)
如果你想让接口更通用,我建议插入一个调用来PyFile_AsFile
处理 Python File 对象,这些对象实际上是文件,而不仅仅是 StringIO 对象。您可以检查返回值以尝试使用您给出的参数作为许多不同的可行类型的输入。
这很令人费解。更好的解决方案是cStringIO
改用它,它为您提供直接的 C API,完全避免调用getvalue
。如果您使用的是 glibc,那么您可以使用将 a直接fopencookie
挂接到对象以实现零拷贝。FILE*
cStringIO