C#托管与C++非托管的情愫

一:非托管 操作 托管,使用委托回调

二:托管  操作   非托管,使用封送

  封送处理方式:

     1.内存拷贝

  2.固定内存地址

  总结如下:

  1.string类型

     把string封送到非托管函数:

           Marshal.StringToHGlobalAnsi、Marshal.StringToHGlobalAuto、Marshal.StringToHGlobalUni,之后调用Marshal.FreeHGlobal释放内存;

          从非托管函数里面取出string:

          Marshal.PtrToStringAnsi、Marshal.PtrToStringAuto、Marshal.PtrToStringUni。

       2.byte[ ](或者基础类型的数组),在封送到非托管函数时确保GC不要回收委托,需要保持引用但不需要Pinned:

       从byte[]拷贝封送到非托管函数:

          Marshal.Copy、GCHandle并指定GCHandleType.Pinned类型(其实就是固定内存直接传送byte[]的原始地址,省去了申请内存和拷贝的开销,速度更快)

         从非托管函数拷贝封送到byte[]:

         Marshal.Copy

    3.委托,在封送到非托管函数时需要确保GC不要回收委托,需要保持引用但不需要Pinned

        从delegate封送到非托管函数:

        Marshal.GetFunctionPointerForDelegate

     从非托管函数里面取出:

        Marshal.GetDelegateForFunctionPointer

    4.结构体,只能使用基础类型和固定长度的数组,并且标记StructLayout的LayoutKind.Sequential属性

  封送到非托管函数:

       Marshal.StructureToPtr

  从非托管函数里面取出:

       Marshal.PtrToStructure

   5.对象,C#的对象不能在Native中进行处理,只能保存以待之后再传回给C#调用,保存的方式为C#用GCHandle引用对象,然后把GCHandle转成IntPtr,传给Native作为指针保存。

注意:有几种情况还是需要手动进行封送的,string的编码是utf8之类的非ansi非utf16编码,则必须手动进行封送同时转换编码。和有频繁的对同一委托进行封送调用。

  

原文地址:https://www.cnblogs.com/HansZimmer/p/10080142.html