在传递给非托管代码之前修复可更新结构?我使用一些旧的API,需要将指向结构的指针传递给异步运行的非托管代码。换句话说,在我将结构指针传递给非托管代码后,非托管代码复制该指针并立即返回。非托管代码可以在后台的另一个线程中访问此结构。我无法控制在另一个线程和线程本身中运行的非托管代码。fixed{}语句不能用于修复,因为它不是为异步非托管修复而设计的。GCHandle只能引用引用,因此必须对结构进行装箱才能使用GCHandle。我试过了,它有效。它的主要问题是您无法从托管代码更新结构。要更新一个结构,首先我们需要将它拆箱,然后更新,然后重新装箱,但是......哎呀......再次装箱?!?这意味着内存中以前的指针仍然指向旧的非最新结构,而新结构有另一个指针,这意味着我需要将新指针传递给非托管代码......不适用于我的情况。如何在没有pin{}语句的情况下将结构固定在内存中,以便我可以在不更改指针的情况下从托管代码更新它?谢谢。编辑:只是想知道......有没有办法固定包含结构的父对象,然后获取指向结构而不是容器对象的指针?不安全代码是一种选择吗?//分配非托管内存Foo*foo=(Foo*)Marshal.AllocHGlobal(sizeof(Foo));//初始化结构foo->bar=0;//调用记住foo的非托管函数UnsafeNativeMethods.Bar(foo);控制台.WriteLine(foo->bar);//更新结构foo->bar=10;//调用使用记住的foo的非托管函数UnsafeNativeMethods.Qux();Console.WriteLine(foo->bar);//释放非托管内存Marshal.FreeHGlobal((IntPtr)foo);这编译并没有抛出异常,但我没有方便的非托管函数来测试它是否有效。来自MSDN:当AllocHGlobal调用LocalAlloc时,它会传递一个LMEM_FIXED标志,这会导致分配的内存被锁定到位。此外,分配的内存不是零填充的。在这种情况下使用固定内存不是一个好主意,因为结构的内存需要长期有效。GCHandle.Alloc()将打包结构并将其存储在堆上。由于它是固定的,它将成为垃圾收集器的长期负担,因为它需要不断地寻找绕过路上岩石的方法。简单的解决方案是在非托管内存中为结构分配内存。使用Marshal.SizeOf()获取结构的大小,使用Marshal.AllocCoTaskMem()分配内存。这将为您提供需要传递给非托管代码的指针。使用Marshal.StructureToPtr()初始化内存。并使用PtrToStructure()读取非托管代码编写的结构的更新。如果您经常这样做,您将不断重复结构。这可能很昂贵,具体取决于结构的大小。为避免这种情况,请使用不安全指针直接访问非托管内存。一些基本语法:usingSystem;使用System.Runtime.InteropServices;classProgram{unsafestaticvoidMain(string[]args){intlen=Marshal.SizeOf(typeof(Test));IntPtrmem=Marshal.AllocCoTaskMem(len);测试*ptr=(测试*)mem;ptr->member1=42;//调用方法//..intvalue=ptr->member1;Marshal.FreeCoTaskMem(mem);}publicstructTest{publicintmember1;您需要使用Marshal.StructureToPtr和Marshal.PtrToStructure将结构编组到本机代码中可用的内存中,而不是固定它。结构示例:[StructLayout(LayoutKind.Sequential)]publicstructOVERLAPPED_STRUCT{publicIntPtrInternalLow;公共IntPtrInternalHigh;公共Int32OffsetLow;公共Int32偏移高;公共IntPtr事件句柄;OVERLAPPED_STRUCT();//在托管代码中编辑结构over_lapped.OffsetLow=100;IntPtrpinned_overlap_struct=Marshal.AllocHGlobal(Marshal.SizeOf(over_lapped));Marshal.StructureToPtr(over_lapped,pinned_overlap_struct,true);//将pinned_overlap_struct传递给非托管代码//pinned_overlap_struct更改...//获取生成的新结构OVERLAPPED_STRUCTnat_ov=(OVERLAPPED_STRUCT)Marshal.PtrToStructure(pinned_overlap_struct,typeof(OVERLAPPED_STRUCT));//查看新值是什么intoffset_low=natL_ov;O//查看新值是什么intoffset_low=natL_ov。Marshal.FreeHGlobal(pinned_overlap_struct);如果让结构包含一个ActOnMe()接口和方法如下:delegatevoidActByRef(refT1p1,refT2p2);接口IActOnMe{ActOnMe(ActByRefproc,refTparam);}structSuperThing:IActOnMe{this;诠释;...voidActOnMe(ActByRef,refTparam){proc(refthis,refTparam);大多数时候,通过将委托传递给静态方法以及对结构的引用以将数据传入或传出方法,应该可以避免创建闭包的开销。此外,将已装箱的SuperThing实例转换为IActOnMe并在调用ActOnMe时使用它,它将公开该装箱实例的字段以进行更新,而不是创建另一个副本,如对其进行类型转换。结构。以上是C#学习教程:在将可更新结构传递给非托管代码之前修复它?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
