map return type of C++ function to byte[][] in Java
I have a c++ function declared as
unsigned char** classify
I am using the following interface file in SWIG
%module PWrap
%include "std_string.i"
%include "arrays_java.i"
%apply byte[][] {unsigned char**};
%{
#include "Classifier.h"
%}
%include "Classifier.h"
which generated some files, including a SWIGTYPE_p_p_unsigned_char object
Now, here's where I try to use this C++ function in Java:
SWIGTYPE_p_p_unsigned_char data = pc.classify();//this works, but I can't do anything with the data object execept pass it to other C++ functions expecting unsigned char**
byte[][] data2 =pc.classify();//this does not work - throws compile开发者_开发知识库 time error
So what am I doing wrong to get this mapping working correctly? I know the dimensions of the matrix, because I pass in the args to the C++ function to set everything up. In other words, I'd be happy with getting the data back in any way as long as I could cast it to byte somehow back in Java.
A char** is not a byte[][]. Only single-dimensional arrays can decay into pointers. What you have got back is an array of pointers to arrays, not an array of arrays.
I'd better use use direct JNI instead of SWIG to have full control over such data types.
Anyway returning char **
is not effective because array pinning can't be used. Probably that's why your SWIG wrapper does not do what you want - your classify
should accept char **
as a parameter and not return it. I don't know SWIG so here is some JNI code.
Java source:
package my;
public class Classifier {
public native void init(); // initialize _ptr with a new Classifier
public native void cleanup(); // destroy Classifier
public native byte[][] classify();
private long _ptr;
}
Method definition in C/C++:
Classifier *getClassifierInstance(JNIEnv *env, jobject obj) {
jfieldID id = env->GetFieldID(env->GetObjectClass(obj), "_ptr", "J");
return (id == NULL) ? NULL : ((Classifier *)env->GetLongField(obj, id));
}
JNIEXPORT jobjectArray JNICALL
Java_my_Classifier_classify(JNIEnv *env, jobject obj) {
Classifier *classifier = getClassifierInstance(env, obj);
char **ptr = classifier->classify();
jobjectArray result = NewObjectArray(env, MATRIX_HEIGHT, FindClass(env, "[B"), NewByteArray(env, 0));
for (int i = 0; i < MATRIX_HEIGHT; ++i) {
jbyteArray row = NewByteArray(env, MATRIX_WIDTH);
SetByteArrayRegion(env, row, 0, MATRIX_WIDTH, ptr[i]);
SetObjectArrayElement(env, result, i, row);
}
return result;
}
Have a look at http://www.ibiblio.org/pub/languages/fortran/append-c.html "Why a double pointer can't be used as a 2D array?"
精彩评论