如何调用含Float[]对应PointerByReference参数的JNA函数及传递Synth实例到JNI Oboe代码
实现方案
可行性说明
完全可以实现该需求,JNA的PointerByReference本质就是原生指针的Java层包装,底层存储的就是C++层的内存地址,直接传递转换即可,没有额外适配成本。
问题1:JNA中数组与Pointer/PointerByReference的转换方法
如果你需要纯JNA场景下调用参数为Pointer的接口,可按以下方式实现:
- FloatArray转Pointer:
val targetFloatArray = FloatArray(requiredLength) // 申请对应长度的原生内存,每个float占4字节 val floatPointer = Memory((targetFloatArray.size * 4).toLong()) // 把Java数组写入原生内存 floatPointer.write(0, targetFloatArray, 0, targetFloatArray.size) // 需要PointerByReference的话再做一层包装 val pbr = PointerByReference(floatPointer)
- 从Pointer读取FloatArray:
val resultArray = floatPointer.getFloatArray(0, requiredLength)
ShortArray的逻辑完全一致,仅需把每个元素的字节数换成2,调用对应getShortArray/写入ShortArray的方法即可。
问题2:Synth实例传递到JNI层并调用的实现步骤
3.1 改造JNI接口
首先修改Kotlin层的JNI方法,新增接收Synth指针地址的参数:
// JNA的Pointer可以直接转成Long类型的原生地址,直接传这个值即可 external fun create(synthHandle: Long): Boolean
调用时传入你持有的handle:
create(handle.value.toLong())
3.2 改造JNI层Create函数,存储Synth指针
修改C++层的Create函数实现,把传入的Long值转成Synth实例指针存储:
// 可以把指针存在全局变量,也可以存在AudioEngine、RecordingCallback的成员变量里,按需选择 static void* g_synth_ptr = nullptr; JNIEXPORT jboolean JNICALL Java_com_sheraz_oboerecorder_AudioEngine_create(JNIEnv *env, jobject obj, jlong synth_handle) { // 直接把jlong转成头文件定义的Synth类型指针即可,比如你的头文件里Synth类型为synth_dev就转成synth_dev* g_synth_ptr = reinterpret_cast<void*>(synth_handle); // 原有Create逻辑保持不变 return JNI_TRUE; }
3.3 修改Oboe音频回调,调用Synth写入方法
直接把Synth写入逻辑加到你现有的回调中即可:
oboe::DataCallbackResult RecordingCallback::onAudioReady(oboe::AudioStream *audioStream, void *audioData, int32_t numFrames) { // 先把Synth的输出写入audioData缓冲区 if(audioStream->getFormat() == oboe::AudioFormat::Float) { // 把g_synth_ptr转成头文件对应的Synth类型指针即可 synth_write_float(reinterpret_cast<synth_dev*>(g_synth_ptr), numFrames, static_cast<float *>(audioData), 0, 2, static_cast<float *>(audioData), 1, 2); } else { synth_write_s16(reinterpret_cast<synth_dev*>(g_synth_ptr), numFrames, static_cast<short *>(audioData), 0, 2, static_cast<short *>(audioData), 1, 2); } // 再执行原有录音逻辑,即可把Synth的输出写入录音文件 mSoundRecording->write(audioData, numFrames); return oboe::DataCallbackResult::Continue; }
注意事项
- 确保Synth实例的生命周期长于Oboe引擎,不要在Oboe还在运行时释放Synth实例,避免野指针崩溃。
- Synth的内存管理还是由原JNA逻辑负责即可,JNI层仅持有指针调用方法,不需要额外申请/释放内存。
内容的提问来源于stack exchange,提问作者Renetik
相关产品推荐
相关产品推荐

