FileInputStream to use that open file descriptor?
Java does have a FileDescriptor class. At first glance,
that would seem to be the answer. The only trouble is, there is only one
constructor, and it gives you an 'invalid' one. Why did they bother?
The answer is that just because there is no apparent way to get a FileDescriptor to point to an arbitrary open file, that doesn't mean there is no way to do it.
Set up your native method in the usual manner, but make sure one of the arguments is a FileDescriptor. Something like this:
public class myDevice {
private native static prepare_fd(String filename, FileDescriptor fdobj);
private FileInputStream in, out;
public myDevice() {
FileDescriptor myDev = new FileDescriptor();
prepare_fd("/dev/tty.modem", myDev);
in = new FileInputStream(myDev);
out = new FileOutputStream(myDev);
}
}
So far, so good. We now have the Java side set up to call our native
code, which will modify the FileDescriptor so that it
refers to the device we will be opening.
I'm not going to detail the vagueries of JNI and how you write it. The
trick in prepare_fd is to just assume that the
FileDescriptor object has an integer field called fd. If
you stuff the number you get from the open() system call,
or from calling fileno() on a FILE *, it will
magically work.
Here's an example:
JNIEXPORT void JNICALL Java_Example_prepare_1fd(JNIEnv *env, jclass _ignore, jstring filename, jobject fdobj) {
jfieldID field_fd;
jclass class_fdesc;
int fd;
char *fname;
fname = (*env)->GetStringUTFChars(env, filename, NULL);
fd = open(fname, O_RDWR | O_NONBLOCK);
(*env)->ReleaseStringUTFChars(env, filename, fname);
class_fdesc = (*env)->GetObjectClass(env, fdobj);
field_fd = (*env)->GetFieldID(env, class_fdesc, "fd", "I");
(*env)->SetIntField(env, fdobj, field_fd, fd);
}