在C#中使用指针作为外部函数的缓冲区

时间:2016-10-06 23:23:13

标签: c# c++ pointers unity3d buffer

我正在将一个外部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的正确工作指针。对此有何帮助?我所有输入数组或使用固定结构的尝试都破坏了程序。

1 个答案:

答案 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();

        }
}