封送浮点*到C#
我有一个DLL,它导出一个返回浮点*的函数,我想在我的C#代码中使用它。我不知道如何封送我的浮点*以便在C#中安全地使用它。 因此,在我的C++ DLL中,我声明:封送浮点*到C#,c#,c++,memory-management,dll,marshalling,C#,C++,Memory Management,Dll,Marshalling,我有一个DLL,它导出一个返回浮点*的函数,我想在我的C#代码中使用它。我不知道如何封送我的浮点*以便在C#中安全地使用它。 因此,在我的C++ DLL中,我声明: static float* GetSamples(int identifier, int dataSize); 在我的C#脚本中,我有: [DllImport ("__Internal")] public static extern float[] GetSamples (int identifier, int dataSize)
static float* GetSamples(int identifier, int dataSize);
在我的C#脚本中,我有:
[DllImport ("__Internal")]
public static extern float[] GetSamples (int identifier, int dataSize);
C++的GETSAMPLE(int,int)分配内存并返回指针数组浮点数组。如何声明C#GetSamples来封送浮点数组,如何访问数据(通过迭代或Marshal.Copy)? 另外,我能从C中删除浮点*还是必须调用另一个C++函数来删除分配的内存?< /P> 编辑: 这就是我到目前为止一直在尝试的。 首先,在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);
}
我真的不知道outPtr是做什么用的。。。我知道我还有一些额外的复制步骤可以删除,我现在只想让它工作。所以这是一个有点复杂的答案 NET不知道如何处理C++内存分配,因此,不管返回<代码>浮点*>代码>,这是最危险的。此外,.NET内存模型是基于COM的,因此它是基于
CoTaskMemAlloc
的,并不是说它在这方面对您有帮助。下面是我的建议:
传递bufferLength为零将返回缓冲区所需的空间,然后可以分配并传入该空间
您需要在C#中为缓冲区分配内存,而在C++中无法分配内存,因此这是一个有点复杂的答案 NET不知道如何处理C++内存分配,因此,不管返回<代码>浮点*>代码>,这是最危险的。此外,.NET内存模型是基于COM的,因此它是基于
CoTaskMemAlloc
的,并不是说它在这方面对您有帮助。下面是我的建议:
传递bufferLength为零将返回缓冲区所需的空间,然后可以分配并传入该空间
您需要在C#中为缓冲区分配内存,但无法在C++中分配它。您控制该DLL的代码吗?是的,我控制该DLL的代码。您控制该DLL的代码吗?是的,我控制该DLL的代码。编写的代码是什么?我尝试过实现这个,但仍然有问题。我声明一个ItpTR,我作为SAMPLE缓冲区,并使用C++中的MimcPy来分配一些数据给它--> MeMCPY(sampleBuffer,MyDATA,BuffelSt*sisiof(浮点));然后在C端,我尝试使用Marshal.ReadByte(dataPointer,I)读取它;,但是我遇到了一个严重的访问错误。我是个新手,有什么建议吗?我将用更多细节更新我的问题。IntPtr包含对要分配的C#数组的引用,它本身只是一个指针持有者。你会调用pINKEK两次,一次得到数组的大小分配(如果你永远不会分配这么多内存,写的是int而不是int),但是如果你用C语言写的改变它也改变C++中的int值,那么分配的大小将以书面形式返回。第二个调用将使用分配给缓冲区intptr的数组,即分配给长度的长度intptr@DavidMenard我已经编辑了我的示例以便更易于使用,但是有一个提醒,您确实需要用C而不是C++进行内存分配,因此我仍然无法调用该方法。问题是我在Unity3d中,不能使用“不安全”,所以不能使用IntPtr.ToPointer()。宣布新的浮动[dataLen];在C边,把它作为浮点*传递给C++也不起作用。在C#中永远不需要使用
不安全的
。书面语言做什么?我尝试过实现这个,但仍然有问题。我声明一个ItpTR,我作为SAMPLE缓冲区,并使用C++中的MimcPy来分配一些数据给它--> MeMCPY(sampleBuffer,MyDATA,BuffelSt*sisiof(浮点));然后在C端,我尝试使用Marshal.ReadByte(dataPointer,I)读取它;,但是我遇到了一个严重的访问错误。我是个新手,有什么建议吗?我将用更多细节更新我的问题。IntPtr包含对要分配的C#数组的引用,它本身只是一个指针持有者。你会调用pINKEK两次,一次得到数组的大小分配(如果你永远不会分配这么多内存,写的是int而不是int),但是如果你用C语言写的改变它也改变C++中的int值,那么分配的大小将以书面形式返回。第二个调用将使用分配给缓冲区intptr的数组,即分配给长度的长度intptr@DavidMenard我已经编辑了我的示例以便更易于使用,但是有一个提醒,您确实需要用C而不是C++进行内存分配,因此我仍然无法调用该方法。问题是我在Unity3d中,不能使用“不安全”,所以不能使用IntPtr.ToPointer()。宣布新的浮动[dataLen];在C边,把它作为浮点*传递给C++也不起作用。在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;
}
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;
}