我有一个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库的多个副本? 谢谢!
答案 0 :(得分:4)
你做不到。动态链接器只会将给定的.so文件加载到进程中一次。
理想情况下,您可以修改库以使其具有轻松的面向对象样式,允许您从配置文件或调用中创建实例并初始化这些实例(而不是进程级静态)。这看起来并不像看起来那么复杂 - 基本上把你所有的状态放在一个结构中,并通过所有调用将指针传递给它。你将有一个马拉松编辑器会话导致一个疲惫的“粘贴”手指,然后一些错误清理。幸运的是,一旦删除静态变量,您将在所有剩余的尝试中获得编译错误。
一个非常讨厌的替代方案可能是在AndroidManifest.xml中声明一些远程进程服务并将库加载到每个服务器中。或者,真正打破android模型(以及随机杀死的理论风险),将库加载到多个按需创建的本机可执行文件中。