2013-02-13 2 views
1

У меня есть следующий метод, который я завернуть с помощью SWIG, чтобы получить доступ к нему в Python:Python и SWIG: Использование StringIO вместо FILE *

void some_class::some_method(FILE *fp, int *pT, int **pO) { 
    fscanf(fp, "lalala", pT); 

Как можно пройти StringIO для первого аргумента? Какую типографию я должен использовать?

+0

Проверка работоспособности: вы просто читаете из 'ФАЙЛА *', не пишите на него? – Flexo

+0

Да, только чтение – warden

ответ

0

Простым решением является создание типовой карты, которая использует 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 для нулевой копии.

+0

Ничего себе, спасибо за обширный ответ! – warden

Смежные вопросы