Domanda

Sto cercando di eseguire un metodo nativo in Java e poi ricevendo un doppio array 2D che posso usare in Java. Ho manipolato con successo i dati in c, ma ora ho bisogno di rimandarlo a Java. Come avrei convertire un doppio array 2D in c da un doppio array 2D in Java?

Ho provato questo semplice codice che ho trovato, ma sfortunatamente non funziona:

jobjectArray convertToArray(JNIEnv *env, double **data, int length1D,
            int *length2D) {
        jsize outerSize = (jsize) length1D; /* EDIT thanks to John Bickers */
        jclass class = (*env)->FindClass(env, "[D"); /* EDIT thanks to Nam San */
        jobjectArray outer = (*env)->NewObjectArray(env, outerSize, class, 0);
        jsize i;
        for (i = 0; i < outerSize; i++) {
            jsize innerSize = (jsize) length2D[i]; /* EDIT thanks to John Bickers */
            jdoubleArray inner = (*env)->NewDoubleArray(env, innerSize);
            (*env)->SetDoubleArrayRegion(env, inner, 0, innerSize, data[i]);
            (*env)->SetObjectArrayElement(env, outer, i, inner);
            (*env)->DeleteLocalRef(env, inner); /* EDIT thanks to Tom Blodget */
        }
        return outer;
    }
.

E questa è la macro chiamata 'GetLength':

#define getLength(x)  (sizeof(x) / sizeof(x[0]))
.

Quando corro questo crea un Mindump (che non riesco a capire):

Sono nuovo per la programmazione JNI e C, quindi ti preghiamo di spiegare piuttosto dettagliata cosa è esattamente sbagliato e come lo aggiusterei.

Grazie in anticipo!

Aggiornamento Ho scoperto che l'errore non riguarda il codice stesso, più sull'array che sto cercando di convertire. Si scopre che un elemento nell'array contiene molte più elementi rispetto agli altri. Sto cercando di leggere da un file MATLAB di livello 4 con aiuto della biblioteca Matio. Forse l'errore si trova lì? Metterò tutto qui sotto:

#include <jni.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <matio.h>
#include "ReadMatFile.h"

//macros
#define getLength(x)  (sizeof(x) / sizeof(x[0]))

//variables
double *dataMatrix[4];
int innerSize[getLength(dataMatrix)];

//functions
jobjectArray convertToArray(JNIEnv *env, double **data, int length1D,
        int *length2D);

JNIEXPORT jobjectArray JNICALL Java_ReadMatFile_readMatFile(JNIEnv *env,
        jobject object, jstring str) {
    const char *fileName = (*env)->GetStringUTFChars(env, str, 0);
    mat_t *matfp;
    matvar_t *matvar;
    printf("%s\n", fileName);
    matfp = Mat_Open(fileName, MAT_ACC_RDONLY | MAT_FT_MAT4);
    if ( NULL == matfp) {
        fprintf(stderr, "Error opening MAT file %s\n", fileName);
        return NULL;
    }
    int i = 0;
    while ( NULL != (matvar = Mat_VarReadNext(matfp))) {
        double *data = (double*) (matvar->data);
        dataMatrix[i] = data;
        innerSize[i] = (int) matvar->nbytes / matvar->data_size;
        Mat_VarFree(matvar);
        matvar = NULL;
        i++;
    }
    Mat_Close(matfp);
    (*env)->ReleaseStringUTFChars(env, str, fileName);
    int outerSize = (int) getLength(dataMatrix);
    return convertToArray(env, dataMatrix, outerSize, innerSize);
}

jobjectArray convertToArray(JNIEnv *env, double **data, int length1D,
        int *length2D) {
    jsize outerSize = (jsize) length1D;
    jclass class = (*env)->FindClass(env, "[D");
    jobjectArray outer = (*env)->NewObjectArray(env, outerSize, class, 0);
    jsize i;
    for (i = 0; i < outerSize; i++) {
        jsize innerSize = (jsize) length2D[i];
        jdoubleArray inner = (*env)->NewDoubleArray(env, innerSize);
        (*env)->SetDoubleArrayRegion(env, inner, 0, innerSize, data[i]);
        (*env)->SetObjectArrayElement(env, outer, i, inner);
        (*env)->DeleteLocalRef(env, inner);
    }
    return outer;
}
.

Un altro aggiornamento

Sembra che l'errore sia nel primo elemento dell'array. Sono sicuro di questo perché se eseguo il codice su un altro array con meno valori funziona perfettamente bene. Ma se cerco di eseguire questo codice in cui sto tornando solo il primo array crea un minidump:

#include <jni.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <matio.h>
#include "ReadMatFile.h"

//macros
#define getLength(x)  (sizeof(x) / sizeof(x[0]))

//variables
double *dataMatrix[4];
int innerSize[getLength(dataMatrix)];

//functions
jobjectArray convertTo1DArray(JNIEnv *env, double *data, int length);

JNIEXPORT jdoubleArray JNICALL Java_ReadMatFile_readMatFile(JNIEnv *env,
        jobject object, jstring str) {
    const char *fileName = (*env)->GetStringUTFChars(env, str, 0);
    mat_t *matfp;
    matvar_t *matvar;
    matfp = Mat_Open(fileName, MAT_ACC_RDONLY | MAT_FT_MAT4);
    if ( NULL == matfp) {
        fprintf(stderr, "Error opening MAT file %s\n", fileName);
        return NULL;
    }
    int i = 0;
    while ( NULL != (matvar = Mat_VarReadNext(matfp))) {
        double *data = (double*) (matvar->data);
        dataMatrix[i] = data;
        innerSize[i] = (int) matvar->nbytes / matvar->data_size;
        Mat_VarFree(matvar);
        matvar = NULL;
        i++;
    }
    Mat_Close(matfp);
    (*env)->ReleaseStringUTFChars(env, str, fileName);
    return convertTo1DArray(env, dataMatrix[1], innerSize[1]);
}

jobjectArray convertTo1DArray(JNIEnv *env, double *data, int length) {
    jdoubleArray arr = (*env)->NewDoubleArray(env, (jsize) length);
    (*env)->SetDoubleArrayRegion(env, arr, 0, (jsize) length, data);
    (*env)->DeleteLocalRef(env, arr);
    return arr;
}
.

Tuttavia, se eseguo il codice sull'elemento successivo nell'array (cioè indice 1 anziché indice 0) non crea un minidump né non riesce a restituire l'array. The La ragione per cui crea un minidump è molto probabilmente perché il primo array contiene 1000004 valori a doppio recuperati da un file MATLAB di livello 4. Quindi questa domanda è già stata risolta, grazie a tutti. Ma sfortunatamente il problema che ho descritto rimane ancora (cioè crea ancora il minidump). Quindi grazie a tutti, probabilmente pubblicherò un'altra domanda riguardante l'enorme problema dell'array ..

È stato utile?

Soluzione

Un grosso problema è che ottenere la lunghezza (dati) non restituisce ciò che ti aspetti.Poiché viene data la funzione un puntatore a un puntatore a un puntatore a un doppio, sizeof (x) è la dimensione di un puntatore a un puntatore e sizeof (x [0]) è la dimensione di un puntatore a un doppio.Il risultato è molto probabilmente 1. All'interno della funzione il tuo codice non ha modo di dire quali sono le dimensioni della matrice dei dati.

Dovresti probabilmente cambiare la funzione in modo che i dati siano solo un doppio *, aggiungere altri due parametri per fornire le due dimensioni dell'array, innerdizione e in uscita, e fare qualche aritmetica per ottenere l'indice in dati quando si chiama SetDoubleArrayregion ().

Altri suggerimenti

Questo è un duplicato di Come restituire 2DARRAY LUNGA CON JNI tranne che vuoi un doppio array 2D invece di un array 2D lungo.Per matrici doppie 2D il tuo FindClass() Il metodo deve trovare "[D" anziché "java/lang/Double"

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top