簡體   English   中英

元帥浮動*到C#

[英]Marshal float* to C#

我有一個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)分配內存,並返回一個指向float數組的指針。 如何聲明C#GetSamples來封送我的float數組,以及如何訪問數據(通過迭代或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 ++中進行分配

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM