Заставить старую библиотеку работать с Perl XS и PerlIO

Я скорее новичок в XS, и я смотрю на изменение существующего модуля XS, который интенсивно использует лежащую в основе библиотеку C старше 15 лет (на самом деле этот модуль - просто клей для этой библиотеки). Проблема в том, что я хотел бы иметь возможность использовать строковый обман PerlIO, например:

open($fh, '<', \$string);

а затем пройти $fh на клей XS, где библиотека ожидает FILE, Проблема в том, что XS имеет:

int
_parse (entry_ref, filename, file, preserve=FALSE)
    SV *    entry_ref;
    char *  filename;
    FILE *  file;
    boolean preserve;

и я предполагаю, что это должно быть:

PerlIO *  file;

Это не работает, конечно, так как должно быть что-то большее. Когда я смотрю на _parse код в библиотеке, он заканчивается в:

AST * bt_parse_entry (FILE *    infile,
                      char *    filename,
                      btshort    options,
                      boolean * status)
{
   AST *         entry_ast = NULL;
   static int *  err_counts = NULL;
   static FILE * prev_file = NULL;

с FILE Типы снова. Теперь я должен начать с основного вопроса: возможно ли это даже без изменения библиотеки; то есть я могу получить псевдо-файловый дескриптор из строкового поведения PerlIO, просто изменив XS?

1 ответ

Решение

Perl API обеспечивает PerlIO_exportFILE() ( Реализация), которая может преобразовать дескриптор PerlIO с файловым дескриптором в stdio FILE указатель. Поскольку PerlIO::Scalar является дескриптором файла "в памяти" без дескриптора файла, преобразование не может быть успешным. Единственный портативный способ передать PerlIO::Scalar дескриптор будет сбрасывать его во временный файл. Менее переносимый способ - использовать stdio, поддерживающий обратные вызовы, такие как реализация BSD, funopen (3).

Другие вопросы по тегам