简体   繁体   English

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

[英]Pass InputStream through JNA to C code as a File Pointer

I've got a DLL written in C (that I can't edit) that has some function prototype that looks like 我有一个用C编写的DLL(我无法编辑),它有一些看起来像的函数原型

#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. 我想创建一个DLL的JNA接口,我不清楚我需要为FILE * bar参数传递什么。 I assume I need to pass an InputStream (which is my preference), but the JNA literature seems sparse on the subject. 我假设我需要传递一个InputStream(这是我的偏好),但JNA文献似乎在这个主题上很少。

What would the Java interface look like? Java界面会是什么样子? and what do I really need to pass to foo? 我真正需要传递给foo的是什么?

Edit: foo assumes bar is the result of an fopen and calls operations like fscanf. 编辑:foo假设bar是fopen的结果,并调用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). 编辑2:最终,我在Java中有一个字符串,我需要在C中读取,就像它是一个文件一样(这可能是一个完全不同的问题)。 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). 理想情况下,我想避免编写文件,这就是为什么将InputStream转换为C文件指针是如此理想(显然非常困难)。

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

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 , eg (pseudocode): 如果您不关心FILE *实际执行的操作,可以使用JNA编写代码来调用fopen ,传入文件名和打开模式,并将结果作为不透明值传递给foo ,例如(伪代码):

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; 不幸的是,标准C库并不是建立在流抽象之上,这意味着你不可能实现你想要的东西,除非你可以打开看起来像文件名但会导致你的字符串数据; 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 :-( 然而,咬住子弹并将字符串保存到临时文件会更容易,然后用fopen打开它:-(

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM