JNI编码和使用JNI连接Java的C/C编码之间的区别

3
我正在使用OpenCV在Android上进行项目开发。我使用C++编码,但希望将程序实现在Android智能手机上。我不想将C++代码转换为Java,只是因为Android是基于Java的,所以我将使用JNI。在我的研究中,我找到了一些真正使用JNI编码风格的代码,但我无法理解如何将我的C++代码转换为JNI代码。我发现,在Android OpenCV示例的教程4中,它仅使用了C++代码,而不像教程3那样。所以这两者之间真正的区别是什么?我想知道JNI编码风格是否会给我更快的性能。目前,我已经能够使用C++并将其与Java集成,但应用程序会崩溃。
从Android OpenCV教程3中:
JNIEXPORT void JNICALL
Java_org_opencv_samples_tutorial3_Sample3View_FindFeatures(JNIEnv* env, jobject,
jint width, jint height, jbyteArray yuv, jintArray bgra)
{
    jbyte* _yuv  = env->GetByteArrayElements(yuv, 0);
    jint*  _bgra = env->GetIntArrayElements(bgra, 0);

    Mat myuv(height + height/2, width, CV_8UC1, (unsigned char *)_yuv);
    Mat mbgra(height, width, CV_8UC4, (unsigned char *)_bgra);
    Mat mgray(height, width, CV_8UC1, (unsigned char *)_yuv);

    cvtColor(myuv, mbgra, CV_YUV420sp2BGR, 4);

    vector<KeyPoint> v;

    FastFeatureDetector detector(50);
    detector.detect(mgray, v);
    for( size_t i = 0; i < v.size(); i++ )
        circle(mbgra, Point(v[i].pt.x, v[i].pt.y), 10, Scalar(0,0,255,255));

    env->ReleaseIntArrayElements(bgra, _bgra, 0);
    env->ReleaseByteArrayElements(yuv, _yuv, 0);
}

来自 Android OpenCV 教程 4:

JNIEXPORT void JNICALL
Java_org_opencv_samples_tutorial4_Sample4View_FindFeatures(JNIEnv*, jobject, jlong
addrGray, jlong addrRgba)
{
    Mat* pMatGr=(Mat*)addrGray;
    Mat* pMatRgb=(Mat*)addrRgba;
    vector<KeyPoint> v;

    FastFeatureDetector detector(50);
    detector.detect(*pMatGr, v);
    for( size_t i = 0; i < v.size(); i++ )
        circle(*pMatRgb, Point(v[i].pt.x, v[i].pt.y), 10, Scalar(255,0,0,255));
}

很抱歉,您可能完全混淆了。您不需要编写“JNI代码”。JNI是Java和本地代码之间的接口。您可以像平常一样将C++编译成库,然后使用JNI引用这些库。Android NDK提供了工具链、示例和文档来完成此操作。 - Simon
另外,请记住,如果您决定使用NDK,则必须为不同的设备重新编译库。NTK / JNI可能会根据上下文提供更好的性能,也可能不会。C ++是一种优秀的语言,但在这种情况下,特别要确保权衡利弊。如果您想获得更具体的帮助,必须添加更具体的代码:D - Robert Mason
这段代码是我从Android OpenCV的第三个教程中学到的: jint* _bgra = env->GetIntArrayElements(bgra, 0); 这段代码是我从Android OpenCV的第四个教程中学到的: Mat* pMatRgb=(Mat*)addrRgba; 这两段代码虽然不同,但大致上执行了相同的过程,对吧? - pduckie
@Simon,我编辑了上面的问题并添加了代码以澄清我的意思。 - pduckie
2个回答

1

1
JNI是Java代码和本地代码(C、C++)之间的层。它依赖于native关键字和静态方法。在您的应用程序中,您将仅使用Java方法和类。您需要将C/C++源代码编译为动态库,即.so文件。
JNI使得编写本地方法成为可能,以处理应用程序无法完全使用Java编程语言编写的情况,例如当标准Java类库不支持特定于平台的功能或程序库时。
您不应总是使用C和C++进行编码,这会增加应用程序的复杂性。
请参见此处

1
附言:我认为从软件设计的角度来看,重写代码将会产生一个更“本地化”的Java应用程序,而不是将C++代码包装在JNI中并访问它。此外,你的代码只做数字计算吗?如果是的话,构建一个.so文件仍然是一个好方法。但是,如果你的代码还有其他功能,比如GUI或系统调用等等,简单地将.so文件移动到Android可能会导致跟踪问题。 - Bondax

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接