通过 JNA 将 InputStream 作为文件指针传递给 C 代码

发布于 2024-08-02 20:11:37 字数 441 浏览 2 评论 0原文

我有一个用 C 编写的 DLL(我无法编辑),它有一些函数原型,看起来

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

我想为 DLL 创建一个 JNA 接口,但不清楚我需要为 FILE *bar 传递什么争论。我假设我需要传递一个 InputStream (这是我的偏好),但 JNA 文献在这个主题上似乎很少。

Java 接口是什么样子的?我真正需要传递给 foo 的是什么?

编辑: foo 假设 bar 是 fopen 的结果并调用 fscanf 等操作。

编辑2:最终,我在Java中有一个字符串,我需要在C中读取它,就好像它是一个文件一样(这可能是一个完全不同的问题)。理想情况下,我希望避免写入文件,这就是为什么将 InputStream 转换为 C 文件指针是如此理想(并且显然相当困难)。

I've got a DLL written in C (that I can't edit) that has some function prototype that looks like

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

I'd like to create a JNA interface to the DLL and it's unclear what I need to pass for the FILE *bar argument. I assume I need to pass an InputStream (which is my preference), but the JNA literature seems sparse on the subject.

What would the Java interface look like? and what do I really need to pass to foo?

Edit: foo assumes bar is the result of an fopen and calls operations like fscanf.

Edit 2: Ultimately, I have a string in Java that I need to read in C as if it were a file, (which might be a different question altogether). Ideally I'd like to avoid writing the file, which is why converting an InputStream to a C file pointer is so desirable (and evidently quite difficult).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

余生共白头 2024-08-09 20:11:37

我不相信你能做到这一点 - 你没有简单的方法来访问 InputStream 实例的内部,甚至 FileInputStream 很可能不会在stdio 文件的顶部 *.要了解您的 Java 界面应该是什么样子,您需要发布有关 foo 函数的更多信息 - 它的作用以及如何使用它。

如果您不关心 FILE * 实际上做了什么,您可以使用 JNA 进行编码来调用 fopen,传入文件名和打开模式,然后传递结果作为不透明值一直到 foo,例如(伪代码):

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

更新: 如果您需要一个包含数据的字符串,您需要将其视为在文件,我想你运气不好。不幸的是,标准 C 库并不是建立在流抽象之上的,这意味着您不太可能实现您想要的目标,除非您可以打开看起来像文件名但通向字符串数据的内容;然而,硬着头皮将字符串保存到临时文件中,然后使用 fopen 打开它会容易得多:-(

I don't believe you can do this - you have no easy way to access the internals of of an InputStream instance, and even a FileInputStream will most likely not be implemented on top of a stdio FILE *. To see what your Java interface should be like, you'll need to post more about the foo function - what it does and how you use it.

If you don't care about what the FILE * actually does, you can code up using JNA to call fopen, passing in the file name and open mode, and pass the result as an opaque value through to foo, e.g. (pseudocode):

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

Update: If you need to have a string which contains data which you need treated as if it were in a file, I think you are out of luck. Unfortunately, the standard C library is not built on top of a stream abstraction, which means that you are unlikely to be able to achieve what you want unless you can open what looks like a filename but leads to your string data; however, it's going to be much, much easier to bite the bullet and save the string to a temporary file, then open that with fopen :-(

堇色安年 2024-08-09 20:11:37

在 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;
}

On POSIX systems, you can do this using a pipe, as long as the string isn't too long (unfortunately "too long" depends on the characteristics of the operating system, but is at least 512 bytes):

#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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文