In case you are right now having the same doubts as author of this post, I might have some good news for you. The following snippet of code was supposed to be part of my upcoming Weka toolbox for SPM8. It copies content of a 2-D full real MATLAB array into java.lang.Double[][] of the same dimensions given as the second argument. I ended up using another solution to pass my data around, but nevertheless, I found out how to correctly handle opaque Java objects from a MEX file using JNI. It took some debugging to discover, that the actual jobject handle is stored at (jobject*)(((char*) mxGetData(prhs[n]))+16), where n – index of your Java object argument. It means that you can use mxGetClassName(prhs[n]) to make sure that it is the expected Java type, in this case java.lang.Double[][] and then do any kind of manipulations using JNI. I didn’t discover what other secrets mxGetData(prhs[n]) holds, therefore I cannot tell you for example how to safely create new Java objects, wrap them in an mxArray and return to MATLAB, but I can propose this simple workaround. Pass a java.lang.Object[] array (or even java.util.Vector<Object>) as parameter to your MEX function and put all your result objects in there. That’it. Mystery solved. I’m pretty sure I will have some use for these findings in the future, maybe you will as well. Cheers!
PS. I tested on 64-bit MATLAB R2011b on Windows. It might be different in other versions but probably the address is the same or very near by.
// // Weka Toolbox for SPM // // Copyright (C) 2012, Stanislaw Adaszewski // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. // #include <mex.h> #include <jni.h> #include <string.h> void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { if (nrhs != 2 || mxGetNumberOfDimensions(prhs[0]) != 2 || !mxIsNumeric(prhs[0]) || mxIsSparse(prhs[0]) || mxIsComplex(prhs[0]) || !mxIsDouble(prhs[0]) || strcmp(mxGetClassName(prhs[1]), "java.lang.Double[][]") || mxGetM(prhs[0]) != mxGetM(prhs[1])) { mexErrMsgTxt("Usage: weka_fast_ml_array_to_java_array(src, dest), where src - 2D full real double array, dest - java.lang.Double[][] with the same dimensions"); } JavaVM *vm = 0; JNIEnv *env = 0; int n; JNI_GetCreatedJavaVMs(&vm, 1, (jsize*) &n); if (n != 1) { mexErrMsgTxt("Couldn't find existing Java VM"); } vm->GetEnv((void**) &env, JNI_VERSION_1_6); if (env == 0) { mexErrMsgTxt("Couldn't get Java environment"); } char *d = (char*) mxGetData(prhs[1]); jobjectArray rows = *((jobjectArray*)(d + 16)); size_t M = mxGetM(prhs[0]); size_t N = mxGetN(prhs[0]); const double *p = mxGetPr(prhs[0]); jclass java_lang_Double = env->FindClass("java/lang/Double"); jmethodID java_lang_Double_init_D = env->GetMethodID(java_lang_Double, "<init>", "(D)V"); for (int m = 0; m < M; m++) { jobjectArray col = (jobjectArray) env->GetObjectArrayElement(rows, m); if (env->GetArrayLength(col) != N) { mexErrMsgTxt("Wrong column length in destination"); } for (int n = 0; n < N; n++) { jobject val = env->NewObject(java_lang_Double, java_lang_Double_init_D, *(p + m * N + n)); env->SetObjectArrayElement(col, n, val); env->DeleteLocalRef(val); } } }