编辑:跳至第2部分以获得更简单的代码。
第1部分: 我正在开发一个项目,我必须从C ++调用Java例程。
我使用以下代码来调用java方法。该参数是一个字符串数组,前两个值用于从硬盘驱动器读取文件并对其进行解码并返回数据。出于测试目的,我返回一个只包含文件中第一个图像的1D整数数组。文件中有更多的图像具有Z深度和时间序列,就像在视频中一样,暂时忽略它们。
mid = m_pJVMInstance->m_pEnv->GetStaticMethodID(imageJ_cls, "getIntData", "([Ljava/lang/String;)[I");
if (mid == nullptr)
cerr << "ERROR: method not found !" << endl;
else {
jobjectArray arr = m_pJVMInstance->m_pEnv->NewObjectArray(2, // constructs java array of 2
m_pJVMInstance->m_pEnv->FindClass("java/lang/String"), // Strings
m_pJVMInstance->m_pEnv->NewStringUTF("str")); // each initialized with value "str"
m_pJVMInstance->m_pEnv->SetObjectArrayElement(arr, 0, m_pJVMInstance->m_pEnv->NewStringUTF("D:\Dev_Environment\Test_Files\\")); // change an element
m_pJVMInstance->m_pEnv->SetObjectArrayElement(arr, 1, m_pJVMInstance->m_pEnv->NewStringUTF("4D_1ch.lsm")); // change an element
jintArray depth = (jintArray)(m_pJVMInstance->m_pEnv->CallStaticIntMethod(imageJ_cls, mid, arr)); // call the method with the arr as argument.
m_pJVMInstance->m_pEnv->DeleteLocalRef(arr); // release the object
}
mid方法正在获得正确的功能。 Java代码执行一些处理并将整数数组返回给C ++以进行进一步处理。
Java代码:
public static int[] getIntData(String[] args) {
int[] test = new int[1];
test[0] = 1;
String dir = args[0];
String name = args[1];
String id = dir + name;
ImageProcessorReader ip_reader = new ImageProcessorReader(
new ChannelSeparator(LociPrefs.makeImageReader()));
try {
IJ.showStatus("Examining file " + name);
ip_reader.setId(id);
int num = ip_reader.getImageCount();
int width = ip_reader.getSizeX();
int height = ip_reader.getSizeY();
ImageStack stack = new ImageStack(width, height);
byte[][][] lookupTable = new byte[ip_reader.getSizeC()][][];
//TODO: Don't know how to handle multiple channels i.e RGb images currently.
// Adding all the slices into a 2D array and returning those values.
int[] test_array = new int[width*height];
int[][][] return_array = new int[height][width][num];
for (int i=0; i<num; i++) {
IJ.showStatus("Reading image plane #" + (i + 1) + "/" + num);
ImageProcessor ip = ip_reader.openProcessors(i)[0];
// Copying the value to the return array.
int[][] temp_array = ip.getIntArray();
for (int h=0; h < height; h++) {
for (int w = 0; w < width; w++) {
return_array[h][w][i] = temp_array[h][w];
if (i==0){
test_array[h*width + w] = temp_array[h][w];
}
}
}
//java.awt.image.BufferedImage awt_Ip = ip.getBufferedImage();
//ImageIO.write(awt_Ip, "jpg", new File("D:\\Dev_Environment\\Test_Files\\Test_Folder\\out" + Integer.toString(i) + ".jpg"));
stack.addSlice("" + (i + 1), ip);
int channel = ip_reader.getZCTCoords(i)[1];
lookupTable[channel] = ip_reader.get8BitLookupTable();
}
IJ.showStatus("Constructing image");
ImagePlus imp = new ImagePlus(name, stack);
// ImagePlus show is leading to java window not responding, maybe it is because this program is not a imageJ plugin but a standalone program.
//imp.show();
//ImagePlus colorizedImage = applyLookupTables(r, imp, lookupTable);
//r.close();
//colorizedImage.show();
IJ.showStatus("");
test[0] = 2;
return test;
}
catch (FormatException exc) {
IJ.error("Sorry, an error occurred: " + exc.getMessage());
test[0] = 3;
}
catch (IOException exc) {
IJ.error("Sorry, an error occurred: " + exc.getMessage());
test[0] = 4;
}
return test;
}
仅用于测试我添加了一个大小为1的测试数组来检查C ++中的输出。我在深度变量中得到0作为返回值。
我的问题是如何将整数数组从Java返回到c ++? jintArray是正确的方式吗?因此,我可以将3D数组从Java返回到C ++吗?
编辑 第2部分: 我用新的Java代码和相同的C ++代码进行了测试,除了现在我正在调用&#34; getInDataS&#34;来自java方面。这是java代码:
public static int[] getIntDataS(String[] args) {
int[] test = new int[10];
test[0] = 10;
test[1] = 10;
test[2] = 10;
test[3] = 10;
test[4] = 10;
test[5] = 10;
test[6] = 10;
test[7] = 10;
test[8] = 10;
test[9] = 10;
return test;
}
我至少在深度变量中得到一些值,但是一旦我尝试读取值,就会抛出访问冲突。 Bothe代码行抛出错误。这是C ++代码:
jintArray depth = (jintArray)(m_pJVMInstance->m_pEnv->CallStaticIntMethod(imageJ_cls, mid, arr));
jsize len = m_pJVMInstance->m_pEnv->GetArrayLength(depth);
jint* body = m_pJVMInstance->m_pEnv->GetIntArrayElements(depth, 0);
答案 0 :(得分:1)
返回int数组完全按照您的描述工作,但调用此类Java方法的JNI函数不是CallStaticIntMethod(),而是CallStaticObjectMethod()。这是导致错误的最可能原因。
要接受C中的二维数组(或更多),请将其声明为jobjectArray,并将每个元素的对象值作为jintArray获取。
请注意,您的C代码会泄漏一些本地引用,如果在循环中调用它,则可能会出现问题。使用PushLocalFrame()和PopLocalFrame()包装此代码可能更容易。