[英]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.