我正在将一个外部C ++函数从dylib导入Unity C#。有问题的功能如下:
[DllImport ("librtcmix_embedded")]
unsafe private static extern int RTcmix_runAudio(void* k, void *outAudioBuffer, int nframes);
它接收指针并将音频信息写入固定大小的缓冲区中的指针。我有一个来自Unity的C#函数,它应该将这些信息带入缓冲区:
void OnAudioFilterRead(float[] data, int channels)
理想情况下,在OnAudioFilterRead的主体内,我将能够声明一个固定大小的指针int *(2048,Unity的音频使用的样本数)并将其输入RTcmix_runaudio的outAudioBuffer参数,然后从中复制信息指向float数组的指针。
void OnAudioFilterRead(float[] data, int channels)
{
int *buffer = new int*(2048); //this line is not proper c#, how do I do this?
RTcmix_runAudio (null, buffer, 2048);
for(int i = 0; i<2048; i++){
data[i] = (float) buffer[i];
}
}
但是,我不知道如何在C#中获得大小为2048的正确工作指针。对此有何帮助?我所有输入数组或使用固定结构的尝试都破坏了程序。
答案 0 :(得分:0)
通过使用Marshal.AllocHGlobal,您可以分配一个8192字节(2048 x 32位样本)的非托管缓冲区,由IntPtr指向并将其传递给DLL。然后使用Marshal.Copy将非托管缓冲区内容复制到托管int []。然后我用Linq来演绎&#39;将缓冲区放入float []。使用FreeHGlobal释放非托管缓冲区。
我假设缓冲区由4个字节的整数组成。如果它实际上包含float,则将目标类型更改为float [],C#将调用正确的Marshal.Copy。
using System;
using System.Linq;
using System.Runtime.InteropServices;
public static class DLL
{
[DllImport("librtcmix_embedded")]
public static extern int RTcmix_runAudio(IntPtr k, IntPtr outAudioBuffer, int nframes);
}
public class MyTest
{
void OnAudioFilterRead(out float[] data, int channels)
{
int[] destination = new int[channels];
IntPtr buffer = Marshal.AllocHGlobal(4*channels);
DLL.RTcmix_runAudio((IntPtr)0, buffer, channels);
Marshal.Copy(buffer, destination, 0, channels);
Marshal.FreeHGlobal(buffer);
data = destination.Select(item => (float)item).ToArray();
}
}