元帅浮动*到C#

Marshal float* to C#

本文关键字:      更新时间:2023-10-16

我有一个DLL,它导出一个返回float*的函数,我想在C#代码中使用它。我不知道如何整理我的float*,以便在C#中安全地使用它。因此,在我的C++DLL中,我声明:

static float* GetSamples(int identifier, int dataSize);

在我的C#脚本中,我有:

[DllImport ("__Internal")]
public static extern float[] GetSamples (int identifier, int dataSize);

C++GetSamples(int,int)分配内存并返回浮点数组的指针。如何声明C#GetSamples以封送我的浮点数组,以及如何访问数据(通过迭代或Marshal.Copy)?此外,我可以从C#中删除float*吗?或者我必须调用另一个C++函数来删除分配的内存吗?

编辑:所以这就是我迄今为止所尝试的。首先,在C#端:

声明:

[DllImport ("__Internal")]
public static extern int GetSamples ([In, Out]IntPtr buffer,int length, [Out] out IntPtr written);

尝试称之为:

IntPtr dataPointer = new IntPtr();
IntPtr outPtr;
GetSamples(dataPointer, data.Length, out outPtr);
for (var i = 0; i < data.Length; i++){
    copiedData[i] = Marshal.ReadByte(dataPointer, i);
}

然后在我的C++库中:

int AudioReader::RetrieveSamples(float * sampleBuffer, size_t dataLength, size_t * /* out */ written)
{
    float* mydata = new float[dataLength];
    //This is where I copy the actual data into mydata
    memcpy(sampleBuffer, mydata, dataLength*sizeof(float));
    delete data;
    return dataLength;
}

我真的不知道outPtr是干什么的。。。我知道我还有一些额外的复制步骤可以删除,我只想现在就让它工作起来。

所以这是一个有点复杂的答案。。。

.NET不知道如何处理C++内存分配,所以无论返回float *,这充其量都是危险的。此外,.NET内存模型是基于COM的,所以它是基于CoTaskMemAlloc的,这并不是说它真的对您有帮助。以下是我的建议:

int AudioReader::RetrieveSamples(
     float * sampleBuffer,
     int dataLength,
     int * /* out */ written)
{
     // assuming mydata is already defined
     if(sampleBuffer == NULL || dataLength == 0)
     {
         *written = sizeof(mydata);
         return -1;
     }
     ZeroMemory(sampleBuffer, dataLength);
     int toCopy = min(dataLength, sizeof(myData));
     //This is where I copy the actual data into mydata
     memcpy(sampleBuffer, mydata, toCopy);
     *written = toCopy;
     return 0;
 }
 [DLLImport("__internal")]
 private static extern int GetSamples(
     [In, Out]IntPtr buffer,
     [In] int length,
     [Out] out int written);
 float[] RetrieveFloats()
 {
     int bytesToAllocate = 0;
     GetSamples(IntPtr.Zero, 0, out bytesToAllocate);
     if(bytesToAllocate == 0)
        return null;
     int floatCount = bytesToAllocate/ sizeof(float);
     float[] toReturn = new float[floatCount];
     IntPtr allocatedMemory = Marshal.AllocHGlobal(bytesToAllocate);
     int written = 0;
     if(GetSamples(allocatedMemory, bytesToAllocate, out written) != -1)
     {
         floatCount = written/sizeof(float);
         Marshal.Copy(allocatedMemory, toReturn, 0, floatCount);
     }
     Marshal.FreeHGlobal(allocatedMemory);
     return toReturn;
 }

传递bufferLength为零将返回缓冲区所需的空间,然后可以分配并传入。

您需要在C#中为缓冲区分配内存,而不能在C++中分配

相关文章:
  • 没有找到相关文章