JNI从实际给出的函数中传递不同的函数参数值

时间:2016-07-04 19:50:48

标签: java c++ java-native-interface armv7 opencv3.1

我有一个本机c ++函数,它作用于从Java通过JNI(OpenCV4Android)传递的cv :: Mat(opencv)对象。

这是我的功能声明:

extern "C" jboolean Java_com_test_JNIActivity_track(JNIEnv *env, jobject obj, jlong inMatGr, jlong inMatRgba, jint currFrame);

这是我访问和打印传递参数的代码:

extern "C" jboolean Java_com_test_JNIActivity_track(JNIEnv *env, jobject obj, jlong inMatGr, jlong inMatRgba, jint currFrame)
{
   ALOG("Native: Rgba@%.8x, Gray@%.8x", inMatRgba, inMatGr);

   cv::Mat& captured_image = *(cv::Mat *)inMatRgba;
   cv::Mat_<uchar>& grayscale_image = *(cv::Mat_<uchar> *)inMatGr;
   ...
}

Java声明部分设置如下:

private native boolean track(long grayAddr, long rgbaAddr, int currFrameNum);

这是OnCameraFrame()方法实现:

public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
    mRgba = inputFrame.rgba();
    mGray = inputFrame.gray();
    Log.d(TAG_LOG, "Java: Rgba@0x" + Long.toString(mRgba.getNativeObjAddr(),16) +
            ", Gray@0x" + Long.toString(mGray.getNativeObjAddr(),16));
    track(mGray.getNativeObjAddr(), mRgba.getNativeObjAddr(), currFrameNum++);
    //Log.d(TAG_LOG, "Java: Frame(" + currFrameNum + ')');
    return inputFrame.rgba();
}

但是,我在Java部分(Mat.getNatvieObjAddr())上设置了两个参数的不同值(在本机函数内部时)。

这些是JNI接口两侧的值:

In Java: 1st argument = 0x405ab288, 2nd argument = 0x557ab9d8
In Native: 1st argument = 0x00000000, 2nd argument = 0x405ab288

最后一个参数是jint并给出了正确的值,这个问题是否与jlong​​在不同体系结构上具有不同大小有关(代码在armv7a处理器上运行)。

我感谢任何帮助。感谢。

1 个答案:

答案 0 :(得分:1)

我自己已经弄明白了,我正在分享给我的人。

private native boolean track(long grayAddr, long rgbaAddr, int currFrameNum);

Java的long类型大小为8字节,jlong​​也是如此(typedef为c ++上的_int64_t或C上的long long,请检查jni.h)。

cv::Mat& captured_image = *(cv::Mat *)inMatRgba;

inMatRgba 是指向 cv :: Mat 对象的指针。在64位机器上,一个指针是8个字节(与jlong​​相同)所以它应该可以正常工作;但是,在32位机器上,指针是4个字节,只有inMatRgba的低4个字节被认为是cv :: Mat对象的地址。如果32位机器是大端(在这种情况下低4字节保持值0),这是一个问题。

<强>解决方案:

我必须为每个案例定义不同的作业:

int *ptrRgba = NULL;   
int *ptrGr = NULL;

if (4 == sizeof(int *) && is_big_endian()) {
   ptrRgba = (int *)&inMatRgba;
   ptrGr = (int *)&inMatGr;
}

cv::Mat& captured_image = ptrRgba ? *(cv::Mat *)(*(ptrRgba+1)) : *(cv::Mat *)inMatRgba;
cv::Mat_<uchar>& grayscale_image = ptrGr ? *(cv::Mat_<uchar> *)(*(ptrGr+1)) : *(cv::Mat_<uchar> *)inMatGr;