来自非托管世界的c#结构可以“实时”更新吗?

本文关键字:实时 更新 结构 世界 | 更新日期: 2023-09-27 18:12:57

假设我从非托管库获得一个指向结构体的IntPtr指针。是否有任何方法,在c#中,从这个指针获得一个"活动"结构,以便如果我调用修改非托管结构,我的"活动"结构立即反映这一点?

我相信标准的方法是使用封送构造一个数据副本,由于各种原因(结构布局、数据类型兼容性、不驻留在。net托管内存中),它不能像这样"活"。但是我找不到任何明确的证据证明c#中不可能有"活"结构。他们是吗?

不去c++/CLI,我能得到的最接近这样的"活"结构是什么?

来自非托管世界的c#结构可以“实时”更新吗?

尝试使用UnmanagedMemoryStream:

这个类支持使用现有的基于流的模型访问非托管内存,并且不需要将非托管内存中的内容复制到堆中。

这意味着你将查找/读取/重置流,但这避免了封送。它仍然不是live在某种意义上,你可能想要在。net属性中包装这些访问。

另一个选择:也许你可以使用System。缓冲区,在获得非托管指针之后。

从技术上讲,您可以设置一个结构,其数据对其他地方所做的更改是"实时的"。然而,你要非常仔细地考虑你是否应该。

根据c#的定义,结构体是一种"值类型"。这意味着一个实例是一个值,如"5",对该值的任何更改在概念上都会导致一个新值。5 + 1 = = 6;这并不意味着当你加1时,5"变成"6,而是意味着5和1两个值加起来等于6。

编程中的

值类型还具有引用类型的另一个特性;它们是"按值"传递的,这意味着当一个值作为参数传递时,它们被认为足够便宜,可以"克隆"。当调用完成时,在方法中对变量值(或子属性)所做的任何更改都将被丢弃,因为所有更改都是对堆栈顶层结构的新副本进行的,而不是对位于堆栈较低位置的原始对象的引用。您必须通过使用refor out关键字显式地覆盖此行为,实际上特别声明原始值应该根据方法中发生的情况而更改。

大多数作为结构体实现的对象都是不可变的,迫使你根据这些规则来处理它们;一旦创建了一个,就不能直接设置它的字段/属性。相反,你必须在该结构体上调用各种方法,这将导致创建一个新结构体。

如果你想创建一个反映来自非管理土地的最新数据的类,首先我会把它变成一个"类",这样当你传递它或试图改变它的成员时,就不会对对象的行为产生混淆。然后,您将基本上创建一个"包装器",它使用Kit前面提到的UnmanagedMemoryStream来获取/设置您作为属性公开的值。这将为您提供一个"响应"对象,该对象可以轮询以获取非托管代码最近设置的任何内容,并将新值写入内存中的正确位置。要非常小心;这段代码将不会是"安全的"(特别是当你回写它的时候),并且通过指针钩入非托管代码是。net中为数不多的几个地方之一,在那里你不仅可以故意使你的程序和非托管c++程序崩溃,还可以使整个机器崩溃。