You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何调用含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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 04:45:00