Простым решением является создание типовой карты, которая использует 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 объекты файлов, которые на самом деле являются файлы, а не только объекты StringIO. Вы можете проверить возвращаемое значение, чтобы попытаться использовать аргумент, который вы предоставили, в виде ряда различных жизнеспособных типов входов.
Это довольно изогнутый. Лучше всего было бы использовать cStringIO
, что дает вам прямой API C, избегая полного звонка до getvalue
. Если вы используете glibc, то вы можете использовать для подключения FILE*
непосредственно к объекту cStringIO
для нулевой копии.
Проверка работоспособности: вы просто читаете из 'ФАЙЛА *', не пишите на него? – Flexo
Да, только чтение – warden