我有一个本机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处理器上运行)。
我感谢任何帮助。感谢。
答案 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;