the*_*rry 6 c++ java java-native-interface pointers reference
我的 Java 本机音频库有问题,但首先,这是我当前的方法:
所以现在我试图弄清楚如何防止从 C++ 或 Java 中删除流。
一种解决方案是在流中创建一个线程,以防止删除。
但我不喜欢这个解决方案......
因此,我搜索了如何使此类对象保持活动状态,并发现可以使用 JNI 进行所谓的“全局引用”。但我不明白它们是只适用于java对象还是两者都适用。
我还尝试了另一种 C++ 指针类型是否可以提供帮助。
我感谢任何帮助或想法,它不一定只是 JNI。C++ 标准库方法/函数/类等也很好:)!
系统信息:
全局流意味着所有 JNI 方法都可以访问该流。
编辑:
好吧,“为了让猫从后面出来”,我正在使用 RtAudio。 实时 C++ 音频库
例子:
//THIS IS C++ CODE
RtAudio audio(RtAudio::WASAPI);
int callback(//Buffer stuff etc.){
//do something
if(data.isEmpty())return 1;//invokes audio.closeStream() but this does NOT closes the stream!
else return 0; //Go on with the stream rather wait for the next call
}
JNIEXPORT void JNICALL openStream(jintArray data){
//This is a outputstream
audio.openStream(&outputParams,....., &callback,....);
audio.startStream();
}
JNIEXPORT void JNICALL fillData(jintArray data){
//filldata again!
stream.start(); //Starts the stream but does nothing, because the stream is deleted because of Java
}
Run Code Online (Sandbox Code Playgroud)
如果我将 openStream 方法更改为此,流将不会被删除,但我正在寻找更好的解决方案......
JNIEXPORT void JNICALL openStream(jintArray data){
//This is a outputstream
audio.openStream(&outputParams,....., &callback,....);
audio.startStream();
**while(true); //ADD THIS AND THE STREAM WON'T BE DELETED!**
}
Run Code Online (Sandbox Code Playgroud)
另一个解决方案是在 RtAudio API 中添加一个“keepInstanceAliveThread”,该线程在 stopStream() 方法之后调用,并在调用 startStream() 或 closeStream() 后删除。我宁愿选择另一种解决方案,但目前还没有任何解决方案。
预结果:
感谢@marcinj:
众所周知,全局对象会导致许多问题,很难控制它们的构造/销毁。
编辑:我在互联网上(也在 stackoverflow 上)发现,析构函数是在 JNI 方法返回后调用的。
1)JAVA线程方式
\n我们可以创建一个新线程,以在使用监视器或条件 while 循环锁定的 JNI 函数中保持运行。
\n然后,单独的调用将通过释放监视器或更改 while 循环中的条件来停止函数中线程的执行。
\n2)JAVA对象引用方式
\n另一种选择是创建对象的全局引用\n Android JNI 和 NewGlobalRef。\n这里可以单独调用 USB 断开连接DeleteGlobalRef
。
我们还可以通过将 C++ 对象传递回 java 层,将其生命周期移至 java\n在多个 jni 调用中保持某种 C++ 对象处于活动状态。\n这里对 USB 断开连接的单独调用将删除对 C++ 对象的任何引用在你的java代码中。
\n执行
\n本机文件 (mynative.cpp)
\nextern "C" JNIEXPORT jobject JNICALL\nJava_com_android_nativecpp_MainActivity_createJniNativeReference(JNIEnv* env, jobject obj, jint size) {\n void* buf = malloc(size);\n jobject sharedbytebuffer = env->NewDirectByteBuffer(buf, size);\n return env->NewGlobalRef(sharedbytebuffer);\n}\n\nextern "C" JNIEXPORT void JNICALL\nJava_com_android_nativecpp_MainActivity_deleteJniNativeReference(JNIEnv* env, jobject obj, jobject sharedbytebuffer) {\n env->DeleteGlobalRef(sharedbytebuffer);\n void* buf = env->GetDirectBufferAddress(sharedbytebuffer); \n free(buf);\n return;\n}\n
Run Code Online (Sandbox Code Playgroud)\nJava 文件(MainActivity.java)
\nimport java.nio.ByteBuffer;\n\nprivate ByteBuffer mJniReference;\n\npublic native ByteBuffer createJniNativeReference(int size);\npublic native void deleteJniNativeReference(ByteBuffer mJniReference);\n\n@Override\nprotected void onCreate(Bundle savedInstanceState) {\n super.onCreate(savedInstanceState);\n mJniReference = createJniNativeReference(1000);\n}\n\n\nprotected void onDestroy() {\n deleteJniNativeReference(mJniReference);\n super.onDestroy();\n}\n
Run Code Online (Sandbox Code Playgroud)\n解释
\n否则,1) 或 2) 的原因是,创建的帧将从堆栈中退出,并删除 JNI 本地引用。
\n当删除所有\xc2\xa0std::thread 引用\xc2\xa0(理想情况下未分离)时,这将结束 C++ 中的所有线程。\n在非分离情况下,在主函数上调用 std::thread 析构函数。退出,或者当线程对象超出范围然后调用\xc2\xa0terminate() 时。\n在分离的情况下,分离的线程在应用程序关闭时退出,这会杀死主机进程。它们也可以被垃圾收集。
\n 归档时间: |
|
查看次数: |
971 次 |
最近记录: |