yanisB
yanisB

Reputation: 89

How to return a 3D array from C to Java?

let me present my situation:

PROBLEM: create a 3D array in c and pass it to java through JNI.

PROGRESS: I've tried many options so far, this is what I came to till now:

#include <jni.h>
#include <stdio.h>
#include<stddef.h>
#include<com_example_c2java_MainActivity.h>

JNIEXPORT jobjectArray JNICALL Java_com_example_c2java_MainActivity_getArray
(JNIEnv *env, jobject obj){
    double a[2][2][2];
    int i,j,k;
    double x = 0;
    jclass doubleClass = (*env)->FindClass(env,"Java/lang/Double");//
    jobjectArray ret  = (*env)->NewObjectArray(env, 2, doubleClass, NULL);


    for( i = 0; i<2; i++){
            for( j = 0; j<2; j++){
                    for( k = 0; k<2; k++){
                        x+=1;
                        a[i][j][k] = x;
                    }
            }
    }

    for( i = 0; i<2; i++){
                jdoubleArray tmp1 = (*env)->NewDoubleArray(env,2);;

                jdoubleArray dim2 = (*env)->NewDoubleArray(env,2);
                for( j = 0; j<2; j++){
                    jdouble tmp2[256];
                    jdoubleArray dim3 = (*env)->NewDoubleArray(env,2);

                    for( k = 0; k<2; k++){

                                            tmp2[k] = a[i][j][k];
                                        }
                    (*env)->SetDoubleArrayRegion(env,tmp1 , j, 2, tmp2);

                }
                (*env)->SetDoubleArrayRegion(env,dim2, 0, 2, tmp1);
                (*env)->SetObjectArrayElement(env,ret, i, dim2);
                (*env)->DeleteLocalRef(env, dim2);
        }

    return ret;


}

java side:

package com.example.c2java;

import android.support.v7.app.ActionBarActivity;
import android.annotation.TargetApi;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        double[][][] arr = getArray();
        Log.i("ffff","-----------------------------"+arr[0][0][0]);
    }
    static{
        System.loadLibrary("C2Java");
    }
    public native double[][][] getArray();
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

}

BUG: Launching the app gives the following logcat error:

02-19 16:20:29.084: E/dalvikvm(20707): VM aborting
02-19 16:20:29.084: A/libc(20707): Fatal signal 11 (SIGSEGV) at 0xdeadd00d (code=1), thread 20707 (.example.c2java)

SOLUTION: your help is needed to find it :)

Upvotes: 0

Views: 178

Answers (1)

Michael
Michael

Reputation: 58467

You seem to have misunderstood what the types involved are.

First of all, Java/lang/Double is not the same as the primitive type double. Secondly, ret should not be an array of doubles, it should be an array of arrays of arrays of doubles.

What you want to do is something like this:

jclass doubleArrayArrayClass = env->FindClass("[[D");
jclass doubleArrayClass = env->FindClass("[D");

// Create an array of arrays of arrays of double
jobjectArray ret  = env->NewObjectArray(2, doubleArrayArrayClass, NULL);

for( i = 0; i<2; i++){
    for( j = 0; j<2; j++){
        for( k = 0; k<2; k++){
            x+=1;
            a[i][j][k] = x;
        }
    }
}

for( i = 0; i<2; i++){
    // ret[i] is an array of arrays of double
    jobjectArray dim2 = env->NewObjectArray(2, doubleArrayClass, NULL);
    for( j = 0; j<2; j++) {
        // ret[i][j] is an array of double
        jdoubleArray dim1 = env->NewDoubleArray(2);
        jdouble tmp[256];
        for( k = 0; k<2; k++){
            tmp[k] = a[i][j][k];
        }
        env->SetDoubleArrayRegion(dim1 , 0, 2, tmp);
        env->SetObjectArrayElement(dim2, j, dim1);
        env->DeleteLocalRef(dim1);
    }
    env->SetObjectArrayElement(ret, i, dim2);
    env->DeleteLocalRef(dim2);
}

(I'm using C++-syntax for the JNI calls, so you'll have to change that back to C-syntax if you must use a C compiler)

Upvotes: 2

Related Questions