提高本机代码的可重用性

时间:2014-08-12 12:10:10

标签: android android-ndk java-native-interface

我试图让一些JNI代码从一个应用程序更容易移植到另一个应用程序。 最终目标是创建一个可以在任何应用程序中使用的本机代码库。

到目前为止我做了什么:

创建了一个Java类,其唯一目的是调用本机方法:

package my.example.nativelib;
public class JavaToC {
    public static void loadLib() {
        System.loadLibrary("myLib");
    }

    public static int fooNative(int[] datas) {

        return foo(datas);
    }
    public native static int foo(int[] datas);
 }

在C ++端实现了JNI_OnLoad以使用javaToC

static const char*  JavaWrapper = "my/example/nativelib/JavaToC";
jint foo(JNIEnv* env, jobject javaThis, jintArray datas)
{
    return 0;
}

jint JNI_OnLoad(JavaVM* pVm, void* reserved) 
{
    JNIEnv* env;
    if (pVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
       return -1;
    }

    JNINativeMethod nm[1];
    nm[0].name = "foo";
    nm[0].signature = "([I)I";
    nm[0].fnPtr = (void*)foo;

    jclass cls = env->FindClass(JavaWrapper);
    env->RegisterNatives(cls, nm, 1);

    return JNI_VERSION_1_6;
}

void JNI_OnUnload(JavaVM* pVm, void* reserved)
{
    JNIEnv* env;
    if (pVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
        return;
    }

    jclass cls = env->FindClass(JavaWrapper);
    env->UnregisterNatives(cls);

    return;
}

所以,我可以在我的应用中的任何地方拨打JavaToC.foo()。比强制您将特定本机调用链接到特定类的方法更方便。 但如果其他人想要使用我的本机代码,他们仍然必须使用JavaToC类创建一个特定的包。

还有另一种方法可以提高JNI本机代码的可重用性吗?

你知道一些我可以用作参考的原生文库吗?

1 个答案:

答案 0 :(得分:0)

我提出的最佳方法是 portable 独立库,然后与JNI包装器代码链接。查看JNativeHook及其支持库libUIOHook。 JNativeHook实现了JNI layer,它是libUIOHook API的简单抽象。然后,后备库可以动态或静态链接到JNI包装程序库,或在任何独立的非Java应用程序中使用。这应该给你非常好的重用,并且不需要通过JVM调试你的本机代码。

我不确定RegisterNatives方法是否真的会为代码重用提供任何帮助......但它会使您的代码变得更加复杂。即使您更改了本机方法名称,它们仍然需要接受所有JNI参数,因此您最终会执行诸如动态加载本机共享库之类的操作,然后尝试将导出的函数映射到可以在运行中使用的内容。 Java ...开始听起来很像JNA