Передайте InputStream через код JNA в C как указатель файла - PullRequest
4 голосов
/ 27 августа 2009

У меня есть DLL, написанная на C (которую я не могу редактировать) с прототипом функции, который выглядит как

#include <stdio.h>
void foo(FILE *bar);

Я хотел бы создать интерфейс JNA к DLL, и неясно, что мне нужно передать для аргумента бара FILE *. Я предполагаю, что мне нужно передать InputStream (что является моим предпочтением), но литература по JNA кажется немногочисленной по этому вопросу.

Как бы выглядел интерфейс Java? и что мне действительно нужно передать в foo?

Редактировать: foo предполагает, что bar является результатом fopen и вызывает такие операции, как fscanf.

Редактировать 2: В конечном счете, у меня есть строка в Java, которую мне нужно прочитать в C, как если бы это был файл (это может быть совсем другой вопрос). В идеале я бы хотел избежать записи файла, поэтому преобразование InputStream в указатель на файл C так желательно (и, очевидно, довольно сложно).

Ответы [ 2 ]

3 голосов
/ 27 августа 2009

Я не верю, что вы можете сделать это - у вас нет простого способа получить доступ к внутренним объектам экземпляра InputStream, и даже FileInputStream, скорее всего, не будет реализован поверх stdio FILE *. Чтобы увидеть, каким должен быть ваш Java-интерфейс, вам нужно больше узнать о функции foo - что она делает и как вы ее используете.

Если вас не волнует, что на самом деле делает FILE *, вы можете кодировать с помощью JNA для вызова fopen, передавая имя файла и режим открытия, и передавая результат в виде непрозрачного значения через foo, например (Псевдокод):

path = "MyFile.txt";
bar = Libc.fopen(path, "r");
Libfoo.foo(bar);

Обновление: Если вам нужна строка, содержащая данные, которые вы должны обработать, как если бы они были в файле, я думаю, вам не повезло. К сожалению, стандартная библиотека C не построена поверх потоковой абстракции, что означает, что вы вряд ли сможете достичь того, чего хотите, если не сможете открыть то, что выглядит как имя файла, но приводит к вашим строковым данным; тем не менее, будет намного, намного проще укусить пулю и сохранить строку во временный файл, а затем открыть его с помощью fopen: - (

0 голосов
/ 27 августа 2009

В системах POSIX вы можете сделать это с помощью канала, если строка не слишком длинная (к сожалению, «слишком длинная» зависит от характеристик операционной системы, но не менее 512 байт):

#include <stdio.h>
#include <unistd.h>
#include <string.h>

int string_to_foo(const char *str, size_t len)
{
    int pipefd[2];
    FILE *infile;

    if (len > PIPE_BUF)
    {
        /* Error - string possibly too long */
        return -1;
    }

    if (pipe(pipefd))
    {
        /* Error - pipe() failed */
        return -1;
    }

    if (write(pipefd[1], str, len) < len)
    {
        close(pipefd[0]);
        close(pipefd[1]);

        /* Error - write() failed */
        return -1;
    }

    close(pipefd[1]);

    infile = fdopen(pipefd[0], "r");

    if (!infile)
    {
        close(pipefd[0]);

        /* Error - fdopen() failed */
        return -1;
    }

    foo(infile);

    fclose(infile);

    return 0;
}
...