作为数组间接c ++返回数据的更快方法

这是一个非常干净和漂亮的解决方案,从非托管C ++代码marsahall结构数组。 它是最简单的完美解决方案,我花了一些时间来理解这个概念,所以在几行代码中,你可以看到C# Main() ,我有一个填充的struct数组准备好’收获’..

 typedef struct { int Id; BSTR StrVal; }Package; extern "C" __declspec(dllexport) void dodata(int requestedLength,int StringSize, Package **Packs){ int count; count=0; *Packs = (Package*)LocalAlloc(0, requestedLength * sizeof(Package)); Package *Cur = *Packs; while(count!= requestedLength) { Cur[count].StrVal = NULL; Cur[count].Id = count; Cur[count].StrVal=SysAllocString(L"abcdefghij"); Cur[count].StrVal[StringSize-1]=count+'0'; ++count; } } 

C#

 [DllImport(@"ExportStructArr.dll", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void dodata(int requestedLength, int StringSize, out IntPtr csPkPtr); [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct csPk { public int V; [MarshalAsAttribute(UnmanagedType.BStr, SizeConst = 10)] public string testStr; } static void Main(string[] args){ int ArrL = 16000; csPk[] Cpk = new csPk[ArrL]; IntPtr CpkPtr = IntPtr.Zero; int szPk = Marshal.SizeOf(typeof(csPk)); dodata(ArrL, 10, out CpkPtr); } 

现在我所要做的就是:

  for (int i = 0; i < Cpk.Length; i++) { Cpk[i] = (csPk)Marshal.PtrToStructure(new IntPtr(CpkPtr.ToInt32() + (szPk * i)), typeof(csPk)); } 

解决方案非常简单,因为您可以看到问题是对数据使用不安全或任何类型的转换,甚至是字节…

我怎样才能优化它以更好地返回数据呢?

编辑:

链接我试图从SO中的其他答案中学习:

  • Hans Passant的回答
  • 来自AbdElRaheim的回答
  • 来自supercat的回答

还尝试了谷歌: 维基百科 , 由stephentoub发布的githubpost

这是一个完整的快速解决方案来填充对象列表,我尽我所能,我很乐意收到意见和建议。

C ++

 typedef struct _DataPacket { BSTR buffer; UINT size; } DataPacket; extern "C" __declspec(dllexport) void GetPacksUnsafe( int size, DataPacket** DpArray ) { int szr = size;int count=0; *DpArray = (DataPacket*)CoTaskMemAlloc( szr * sizeof( DataPacket )); if ( DpArray != NULL ) { DataPacket* CurPack = *DpArray; for ( int i = 0; i < szr; i++, CurPack++ ) { CurPack->size = i; CurPack->buffer = SysAllocString(L"SomeText00"); CurPack->buffer[9]=i+'0'; } } } 

C#

  [DllImport(@"ExportStructArr.dll", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void GetPacksUnsafe(int size, PackU** outPackUArr); [StructLayout(LayoutKind.Sequential)] public unsafe struct PackU { public char* StrVal; public int IntVal; } public static unsafe List PopulateLstPackU(int ArrL) { PackU* PackUArrOut; List RtLstPackU = new List(ArrL); GetPacksUnsafe(ArrL, &PackUArrOut); PackU* CurrentPack = PackUArrOut; for (int i = 0; i < ArrL; i++, CurrentPack++) { RtLstPackU.Add(new PackU(){ StrVal = CurrentPack->StrVal, IntVal=CurrentPack->IntVal}); } Marshal.FreeCoTaskMem((IntPtr)PackUArrOut); for (int i = 0; i < 10; i++) { Console.WriteLine("{0}", new string(RtLstPackU[i].StrVal)); } return RtLstPackU; } 

使用代码尽可能简单

  static unsafe void Main(string[] args) { int ArrL = 100000; List LstPackU; LstPackU = PopulateLstPackU(ArrL); } 

那里有一个自定义数据列表和子弹一样快。

编辑

使用指针而不是字符串:

 typedef struct _DataPackCharPnt { char* buffer; UINT IntVal; } DataPackCharPnt; extern "C" __declspec(dllexport) void GetPacksPnt( int size, DataPackCharPnt** DpArrPnt ) { int count = 0; int TmpStrSize = 10; *DpArrPnt = (DataPackCharPnt*)CoTaskMemAlloc( size * sizeof( DataPackCharPnt )); DataPackCharPnt* CurPackPnt = *DpArrPnt; char dummyStringDataObject[]= "abcdefgHi"; for ( int i = 0; i < size; i++,CurPackPnt++ ) { dummyStringDataObject[9] = i+'0'; CurPackPnt->IntVal=i; CurPackPnt->buffer = (char*)malloc(sizeof(char)*TmpStrSize); strcpy(CurPackPnt->buffer, dummyStringDataObject); } } 

减少了从10到7毫秒的时间,填充了100k元素

我可以省略创建buffer任何部分吗?

  • dummyStringDataObject的职责是模拟工作,比如获取一个文件名然后用它的值设置缓冲区,所以除了这个额外的时间,这是这个函数的全部目的,返回一些未知的值和字符串的长度......

你能进一步优化吗?