65,186
社区成员




[System.Runtime.InteropServices.DllImport(@"NativeLib.dll",
EntryPoint = "MthCopy",
CharSet = System.Runtime.InteropServices.CharSet.Ansi,
CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall)]
private static extern int MthCopy(byte[] Source, ref IntPtr Trans, int Len);
[System.Runtime.InteropServices.DllImport(@"NativeLib.dll",
EntryPoint = "MthPtrArrayFree",
CharSet = System.Runtime.InteropServices.CharSet.Ansi,
CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall)]
private static extern int MthPtrArrayFree(IntPtr PtrArray);
调用代码:
int Len = 4;
byte[] Source = new byte[] { 1, 2, 3, 4 };
IntPtr Trans = IntPtr.Zero;
MthCopy(Source, ref Trans, 4);
byte[] TransArr = new byte[Len];
//复制或者用unsafe直接访问指针
System.Runtime.InteropServices.Marshal.Copy(Trans, TransArr, 0, TransArr.Length);
MthPtrArrayFree(Trans);
extern "C" __declspec(dllexport) int__stdcall MthCopy(BYTE *Source, BYTE *&Trans, int Len);
extern "C" __declspec(dllexport) int__stdcall MthPtrArrayFree(void *PtrArray);
int MthCopy(BYTE *Source, BYTE *&Trans, int Len)
{
Trans = new BYTE[Len];
memcpy_s(Source, Len, Trans, Len);
}
int MthPtrArrayFree(void *PtrArray)
{
if (PtrArray)
{
delete[] PtrArray;
PtrArray = nullptr;
}
return 0;
}
switch (nBytes)
{
case 1:
delete[] reinterpret_cast<int8_t*>(PtrArray);
break;
case 2:
delete[] reinterpret_cast<int16_t*>(PtrArray);
break;
case 4:
delete[] reinterpret_cast<int32_t*>(PtrArray);
break;
case 8:
delete[] reinterpret_cast<int64_t*>(PtrArray);
break;
// 其他case,如果你还有其他长度的自定义类型的话
default:
break;
}
不要去直接delete[] void*类型,因为这样做的后果是未定义的。总体上来说,这样写一个释放各种类型数组的方法是有些奇怪的。不如用下面的方式,让C++在合适的时候自己销毁,不用C#通知。它自己自然知道类型是什么。
2. 要缓存,但这也没什么不好的,请求附有上下文就不会混淆。例如你请求一次长度,C++不仅返回长度,而且返回一个号码。号码和缓存的对应放在unordered_map中。你要求填充时候,呈上对应的号码就能得到正确的缓存。这样多次请求就能够区分开。缓存的东西被取一次就会被销毁,过了很长时间没人取也会被销毁。
这自然需要多一次内存复制。但是512*512的32位图像是1 MB,内存复制至多0.5 ms。你的一帧就得17~33 ms。究竟瓶颈在不在这里,是不需要过早下结论的。
[System.Runtime.InteropServices.DllImport(@"NativeLib.dll",
EntryPoint = "MthCopy",
CharSet = System.Runtime.InteropServices.CharSet.Ansi,
CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall)]
private static extern int MthCopy(in byte[] Source, ref IntPtr Trans, int Len);
另外,如上我在byte前加上了in修饰符,程序返回的数组值变成的随机的,这个in该怎么用?
template<typename T>
int MthPtrArrayFree(T *PtrArray)
{
if (PtrArray)
{
delete[] PtrArray;
}
return 0;
}
调用:
float * arr = new float[100];
MthPtrArrayFree(arr);
arr = nullptr;
调用的时候不需要写成MthPtrArrayFree<float>(arr)。因为你传入的数组自带类型,编译器能自动推断出来T是什么。
但最好还是不要写这样的代码。
1. 方法里面的 PtrArray = nullptr 这句没有用,因为PtrArray只是你传入的指针的副本。想让外面数组的指针变为nullptr,要么像上面的代码这样调完MthPtrArrayFree后再写arr = nullptr,要么这个方法变成int MthPtrArrayFree(T ** PtrPtrArray),里面写*PtrPtrArray = nullptr。调用时候MthPtrArrayFree(&arr)。
2. 尽量用RAII的方法管理资源。能用智能指针就尽量用智能指针。
[/quote]我知道有些解决方案用泛型,问题是这个函数是用于c#调用的,我应该怎么做比较合适
template<typename T>
int MthPtrArrayFree(T *PtrArray)
{
if (PtrArray)
{
delete[] PtrArray;
}
return 0;
}
调用:
float * arr = new float[100];
MthPtrArrayFree(arr);
arr = nullptr;
调用的时候不需要写成MthPtrArrayFree<float>(arr)。因为你传入的数组自带类型,编译器能自动推断出来T是什么。
但最好还是不要写这样的代码。
1. 方法里面的 PtrArray = nullptr 这句没有用,因为PtrArray只是你传入的指针的副本。想让外面数组的指针变为nullptr,要么像上面的代码这样调完MthPtrArrayFree后再写arr = nullptr,要么这个方法变成int MthPtrArrayFree(T ** PtrPtrArray),里面写*PtrPtrArray = nullptr。调用时候MthPtrArrayFree(&arr)。
2. 尽量用RAII的方法管理资源。能用智能指针就尽量用智能指针。