从Java实例化JNI库的多个副本

时间:2014-08-27 18:44:17

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

我有一个JNI库,我用它来捕获传感器(主要是加速度计和陀螺仪)数据,并对所述数据做一些特征检测算法。检测到的功能可通过一些配置文件进行配置。检测到功能时,JNI使用回调来通知java端应用程序。这一切都很有效。

现在我希望能够同时运行同一个JNI库的多个实例(这样我就可以同时识别多个配置文件中的功能)。为此,我编写了一个“包装器”类,它实现了JNI库的回调,并负责库的所有初始化。我计划简单地实例化这个类并分别使用每个实例。我发现虽然每个包装器实例都是不同的,但是这些库在实例中重用,就像静态声明的那样。当我尝试从Wrapper类的第二个实例初始化库时,我发现它已经初始化了。

这是一个类似于我编写的代码的包装类:

public class JNIWrapper {

    public native int initializeJNI(String configPath);
    public native void endProcessing();
    public native int getInstanceIdFromJNI();

    public JNIWrapper(){
        try {
            System.loadLibrary("libjnicode.so");
        }
        catch (Exception e) {
            Log.e("JNI", "WARNING: Could not load libjnicode.so: " + e.getMessage());
        }
    }

    public int initialize(String configPath){
        return initializeJNI(configPath);
    }
    public void stop(){
        endProcessing();
    }
    public void callbackFromJNI(int output, int instanceId){
        //notify the subscribed application(s) of the feature detection
        //via message passing.
    }
}

有谁知道如何实例化JNI库的多个副本? 谢谢!

1 个答案:

答案 0 :(得分:4)

你做不到。动态链接器只会将给定的.so文件加载到进程中一次。

理想情况下,您可以修改库以使其具有轻松的面向对象样式,允许您从配置文件或调用中创建实例并初始化这些实例(而不是进程级静态)。这看起来并不像看起来那么复杂 - 基本上把你所有的状态放在一个结构中,并通过所有调用将指针传递给它。你将有一个马拉松编辑器会话导致一个疲惫的“粘贴”手指,然后一些错误清理。幸运的是,一旦删除静态变量,您将在所有剩余的尝试中获得编译错误。

一个非常讨厌的替代方案可能是在AndroidManifest.xml中声明一些远程进程服务并将库加载到每个服务器中。或者,真正打破android模型(以及随机杀死的理论风险),将库加载到多个按需创建的本机可执行文件中。