如何使用 Float[] 的 PointerByReference 参数调用函数?

How can I call function with PointerByReference arguments for a Float[]?

我有一个使用一些 C++ 编译代码的库,我想使用这个和其他函数来尝试一下,但它们都使用 Pointer 和 PointerByReference 作为参数而不是普通类型。

fun writeSampleFloat(length: Int,
                         leftOut: PointerByReference /*Float[]*/,
                         rightOut: PointerByReference/*Float[]*/)

我看到它使用了 JNA 库,但我找不到如何通过引用 Float[] 或 FloatArray 的指针或 ShortArray 的指针来获取指针。

好的所以我正在使用在使用 jna 的库项目中加载的合成器实例,我想通过使用我在其他库项目中使用 jni 的双簧管示例从中录制声音。所以基本上一切正常我可以使用合成器并且双簧管示例可以从麦克风渲染声音我的想法是记录合成器是将合成器的实例作为对双簧管 cpp 代码的本机引用传递所以我可以在那里使用渲染回调从中写入数据合成器。我可以看到如何正确写入数据,但我不知道如何将实例传递给那里。我的第一个问题是不同的,因为我的第一个想法是我将调用 java 形式的双簧管渲染回调,但因为这是一些实时音频的东西,所以我认为这是不可能的和磨损的方法。所以我想传递那个合成器我已经在双簧管中包含 headers 个合成器 ...

所以我的 kotlin/java 项目中有 JNA val handle: PointerByReference 引用合成器实例。我还可以像这样使用 jni 访问双簧管代码:

 external fun create(): Boolean

在cpp中是这样定义的:

Java_com_sheraz_oboerecorder_AudioEngine_create(JNIEnv *env, jobject obj)

我能否以某种方式传递该合成器句柄,以便我可以将 cpp 中的合成器句柄转换为我包含在 cpp 中的实际类型,并在其上调用该渲染函数?

我知道最好用 jna 来写,但这个 cpp 世界对我来说很难。我只需要找到一种方法来调用该合成器实例我看到示例如何从合成器写入数据:

onAudioReady(AudioStream *stream, void *audioData, int32_t numFrames)
    {
    if(stream->getFormat() == AudioFormat::Float)
            {
                synth_write_float(dev->synth, numFrames, static_cast<float *>(audioData), 0, 2, static_cast<float *>(audioData), 1, 2);
            }
            else
            {
                synth_write_s16(dev->synth, numFrames, static_cast<short *>(audioData), 0, 2, static_cast<short *>(audioData), 1, 2);
            }
 return DataCallbackResult::Continue;
    }

我拥有的这个功能可以很好地呈现来自麦克风的音频并已经保存到文件中。现在我有了这个

oboe::DataCallbackResult
RecordingCallback::onAudioReady(oboe::AudioStream *audioStream, void *audioData,
                                int32_t numFrames) {
   mSoundRecording->write(audioData, numFrames);
return oboe::DataCallbackResult::Continue;
}

我希望我能以某种方式将我的 JNA 句柄传递到那里,并在合成器形式的音频渲染回调中调用该函数。这个问题开始听起来太复杂了,也许是另一个问题。

由于您没有为特定调用包含更多 API,我无法直接回答您的实施问题,但我会解决问题中有关类型的部分。

在 C(和 C++)中,数组存储在连续的本机内存中。如果您知道类型(在这种情况下为 float),您可以简单地从指针偏移以获取适当的元素,例如,foo[0] 位于数组的指针位置,foo[1] 将位于该指针位置加上等于类型字节大小的偏移量(浮点数为 4 个字节)等等。

PointerPointerByReference是JNA类型。 PointerByReference是一个指向Pointer的指针;您可以调用 PointerByReference() 上的 getValue() 函数来检索此指针。

根据我阅读本文的方式 API,该指针实际上是浮点数组的开头,因此您只需使用该指针并从其位置检索数组。

所以这可能是您需要做的:

length len = 123; // I assume you know this length

// call the function with your length

Pointer p = leftOut.getValue();
float[] leftArray = p.getFloatArray(0, len);

Pointer q = rightOut.getValue();
float[] rightArray = q.getFloatArray(0, len);

可能还有更多内容,具体取决于 API 是否分配了本机浮点数组内存(在这种情况下寻找释放该内存的函数)或者您是否需要自己分配本机内存,在这种情况下你会这样做:

// allocate memory for the float array of size len
Memory m = new Memory(4 * len);
// Memory extends pointer so just pass this to the PBR constructor
PointerByReference leftOut = new PointerByReference(m);
// now pass leftOut to the method

仅使用 JNA 时,很少需要处理指针的实际本机值。但是,在您编辑的问题中,您似乎想要与 JNI 代码进行交互。在这种情况下,您会希望将指针值传递给那些函数。可以通过

获得
long peer = Pointer.nativeValue(p); // or m or whatever the pointer is