Having an OutputStream write in a C buffer using JNI

Radu :

I am trying to process DNG files (which I get from DngCreator) in my C program. I don't want to save it to disk in Java and then load it from C, because it wastes time and wears down the flash memory (I need about 40 DNGs per session, so that's over 800 MB). I am not very familiar with Java, but is there a way to override OutputStream and add my own JNI call?

Stephan Schlecht :

Assuming you have a DNG creation function that can work with an OutputStream, you could instantiate a ByteArrayOutputStream, pass it as a parameter to your DNG creation function, and later get the byte array with a method call toByteArray().

This can then be passed to a native C library.

In Code this could look like this:

package com.software7.jni;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import static java.nio.charset.StandardCharsets.UTF_8;

public class Main {
    private native void transferDng(byte[] data);

    private void someDNGCreationFunction(OutputStream outputStream)
            throws IOException {
        outputStream.write("hello world!".getBytes(UTF_8));
    }

    private void test() throws IOException {
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            someDNGCreationFunction(baos);
            transferDng(baos.toByteArray());
        }
    }

    public static void main(String[] args) {
        System.loadLibrary("Native");
        Main m = new Main();
        try {
            m.test();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

The native side could then retrieve the data from the byte array, e.g. see this fine answer https://stackoverflow.com/a/38787614/2331445.

#include <string.h>
#include <stdlib.h>
#include <jni.h>
#include "com_software7_jni_Main.h"


JNIEXPORT void JNICALL Java_com_software7_jni_Main_transferDng
  (JNIEnv *env, jobject obj, jbyteArray dng) {
    jsize num_bytes = (*env)->GetArrayLength(env, dng);
    jbyte *b = (*env)->GetByteArrayElements(env, dng, 0);
    char *buffer = malloc(num_bytes);
    memcpy(buffer, b, num_bytes);
    (*env)->ReleaseByteArrayElements(env, dng, b, 0);
    //do something with the buffer, here a printf only for testing 
    printf("%.*s", num_bytes, buffer);
    free(buffer);
    return;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=360826&siteId=1
Recommended