0

我有一个本机 c++ 函数,它作用于通过 JNI(OpenCV4Android)从 Java 传递的 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 处理器上运行)。

我很感激任何帮助。谢谢。

4

1 回答 1

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;
于 2016-07-05T17:27:15.863 回答