java - C:将二维 double 组转换为java二维 double 组

标签 java c arrays java-native-interface minidump

我正在尝试在 java 中运行 native 方法,然后接收可在 java 中使用的二维 double 组。我已经成功地在 C 中操作了数据,但现在我需要将它发送回 java。我如何将 C 中的二维 double 组转换为 Java 中的二维 double 组?

我已经尝试了我想出的这个简单代码,但不幸的是它不起作用:

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

这是名为“getLength”的宏:

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

当我运行它时,它会创建一个 mindump (我听不懂):

我是 JNI 和 C 编程的新手,所以请详细解释到底出了什么问题以及我将如何解决它。

提前致谢!

更新 我发现错误与代码本身无关,更多与我尝试转换的数组有关。事实证明,数组中的一个元素包含的元素比其他元素多得多。我正在尝试在库 matio 的帮助下读取 4 级 matlab 文件。也许错误就在那里?我将所有内容放在下面:

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

另一个更新

似乎错误在数组的第一个元素中。我对此很确定,因为如果我在另一个值较少的数组上运行代码,它工作得很好。但是如果我尝试在我只返回第一个数组的地方运行这段代码,它会创建一个小型转储:

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

但是,如果我在数组中的下一个元素(即索引 1 而不是索引 0)上运行代码,它不会创建小型转储,也不会返回数组失败。它创建小型转储的原因很可能是因为第一个数组包含从 4 级 matlab 文件中检索到的 1000004 个 double 值。所以这个问题已经解决了,感谢大家。但不幸的是,我描述的问题仍然存在(即它仍然会创建小型转储)。所以谢谢大家,我可能会发布另一个关于巨大数组问题的问题..

最佳答案

一个大问题是 getLength(data) 没有返回您期望的结果。因为函数被赋予一个指向 double 指针的指针,所以 sizeof(x) 是指向指针的指针的大小,而 sizeof(x[0]) 是指向 double 的指针的大小。结果很可能是 1。在函数内部,您的代码无法判断数据矩阵的维数。

您可能应该更改该函数,使数据只是一个 double *,再添加两个参数以提供两个数组维度,innerSize 和 outerSize,并在调用 SetDoubleArrayRegion() 时进行一些算术运算以获取数据中的索引。

关于java - C:将二维 double 组转换为java二维 double 组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21065850/

相关文章:

java - 部署到 tomcat 进行测试的最简单方法,我将 .war 文件保存到哪个文件夹?

java - 如何使用滑入或淡入效果更改 JFrame 的内容 Pane

c - 如何测试指针是否在数组内?

c - 在 C 中初始化 char 时 0 vs '\0'

c - C语言中,如何用指针计算一个字符串中有多少个元音字母?

php - 使用 foreach PHP 排序数据显示最近 30 天的数据

java - 我的 Recyclerview 加载无限时出错

java ant Eclipse 运行报错

arrays - 什么是循环排序数组?

javascript - 如何访问字典中的特定元素?