是否可以在没有 pin_ptr 的情况下将托管字节数组转换为本机结构,以免对 GC 造成太多干扰?
Is it possible to cast a managed bytes-array to native struct without pin_ptr, so not to bug the GC too much?
仅使用 pin_ptr
就可以将托管 array<Byte>^
转换为某些非托管 struct
,据我所知,例如:
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
方式在这里不是一个选项...)
您可能不会用 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;
}
这里根本没有固定,但这只是因为托管结构存储在堆栈中,因此首先不可重定位。
这是一个复杂的例子,因为你可以这样写:
static void DoSomething()
{
NativeStruct native;
native.data[42] = 42;
}
...编译器会在幕后为您执行类似的技巧。
仅使用 pin_ptr
就可以将托管 array<Byte>^
转换为某些非托管 struct
,据我所知,例如:
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
方式在这里不是一个选项...)
您可能不会用 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;
}
这里根本没有固定,但这只是因为托管结构存储在堆栈中,因此首先不可重定位。
这是一个复杂的例子,因为你可以这样写:
static void DoSomething()
{
NativeStruct native;
native.data[42] = 42;
}
...编译器会在幕后为您执行类似的技巧。