只有使用array<Byte>^
,AFAIK,才能将托管struct
投放到某个非托管pin_ptr
,例如:
void Example(array<Byte>^ bfr) {
pin_ptr<Byte> ptr = &bfr[0];
auto data = reinterpret_cast<NonManagedStruct*>(ptr);
data->Header = 7;
data->Length = sizeof(data);
data->CRC = CalculateCRC(data);
}
但是,以任何方式使用interior_ptr
?
我更倾向于使用低级方式处理托管数据(使用union
s,struct
- 位字段等等),而无需固定数据 - 我可能是持有此数据已有相当长的时间,并且不想骚扰GC
。
我不想将托管数据复制到本机和后台(因此这里不能选择Marshaling
方式...)
答案 0 :(得分:2)
您可能无法使用pin_ptr
骚扰GC - 与GCHandle
不同,它非常轻量级。
GCHandle::Alloc(someObject, GCHandleType::Pinned)
实际上会将对象注册为固定在GC中。这使您可以在较长的时间内和函数调用之间固定对象,但GC必须跟踪该对象。
另一方面,pin_ptr
被转换为IL代码中的固定本地。 GC没有收到有关它的通知,但它会在集合期间看到该对象仅固定 。也就是说,当在堆栈上查找对象引用时,它会注意到它的固定状态。
如果确实想要,您可以通过以下方式访问堆栈内存:
[StructLayout(LayoutKind::Explicit, Size = 256)]
public value struct ManagedStruct
{
};
struct NativeStruct
{
char data[256];
};
static void DoSomething()
{
ManagedStruct managed;
auto nativePtr = reinterpret_cast<NativeStruct*>(&managed);
nativePtr->data[42] = 42;
}
这里根本没有固定,但这只是因为托管结构存储在堆栈中,因此首先不可重定位。 / p>
这是一个令人费解的例子,因为你可以写:
static void DoSomething()
{
NativeStruct native;
native.data[42] = 42;
}
...并且编译器将为您执行类似的技巧。