2016-07-04 25 views
0

我有一个本地C++函数,它作用于通过JNI(OpenCV4Android)从Java传递的cv :: Mat(opencv)对象。JNI从实际给出的函数参数中传递函数参数的不同值

这是我的函数声明:

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: [email protected]%.8x, [email protected]%.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: [email protected]" + Long.toString(mRgba.getNativeObjAddr(),16) + 
      ", [email protected]" + 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

的本地函数的代码是从你的问题遗漏。 – Michael

+0

@Michael我在访问参数的地方添加了代码片段。 – EHH

回答

1

我已经知道了我自己,我分享谁在我的情况。

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

Java的长型是在大小为8个字节,所以不jlong​​(如typedef的第C要么_int64_t ++或长长上C,检查jni.h)。

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

inMatRgba是一个指向CV ::垫对象。在64位机器上,指针是8个字节(与jlong​​相同),所以它应该可以正常工作;然而,在32位机器上,指针是4个字节,并且只有inMatRgba的低4字节被认为是cv :: Mat对象的地址。如果32位机器是big endian(在这种情况下,低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;