sla*_*ppy 5 c# garbage-collection pointers unsafe
在C#项目中,我需要通过在结构中放置引用来传递对象参数.即我有一个传递给调度员的结构
struct SOMESTRUCT
{
public int lpObject;
}
Run Code Online (Sandbox Code Playgroud)
其中lpObject包含指向自定义对象的指针
class SomeClass
{
private string foo;
}
Run Code Online (Sandbox Code Playgroud)
并且SOMESTRUCT结构从方法传递到方法,最终到达我的代码.我无法修改执行流程和奇怪的SOMSTRUCT系统,所以我猜测唯一的解决方案是将我的对象转换为这样的指针:
var myObject = new SomeClass();
GCHandle GC = GCHandle.Alloc(myObject, GCHandleType.Pinned);
int myRef = GC.AddrOfPinnedObject().ToInt32();
GC.Free();
SOMESTRUCT struct;
struct.lpObject = myRef;
someMethod(struct);
Run Code Online (Sandbox Code Playgroud)
但是,我无法弄清楚如何从lpObject字段中检索myObject成员.像这样的东西:
SomeClass myObject = CastPointerToObject(struct.myRef) as SomeClass;
Run Code Online (Sandbox Code Playgroud)
有办法做到这一点,还是不可能?如何告诉垃圾收集器处理对象?我应该创建一个新的垃圾收集对象并按字段复制数据字段吗?
TYIA,
否否否NO NO !!!
这个
struct SOMESTRUCT
{
public SomeClass object_ref;
}
Run Code Online (Sandbox Code Playgroud)
是在结构中存储引用的正确方法。
您编写的代码和接受的答案已 100% 损坏。
返回的地址GC.AddrOfPinnedObject(GCHandle)仅在GCHandle完好无损时有效。你不能打电话GCHandle.Free,你不能让GCHandle收集。在您的代码中,地址在您存储它时已经毫无意义。
但是您应该让 .NET 在垃圾回收期间通过使用引用类型的变量来管理指针。那么你就不需要跳过箍了。获取托管对象地址的唯一原因是将其传递给现有的本机 DLL 函数时,该函数将在返回后保存指针。例如,它对于 OpenGL 缓冲区数组是必要的。调用其他 C# 方法时,从来没有必要这样做。
如果 SOMESTRUCT 实际上是您没有提到的某些 DLL 函数使用的本机数据类型,那么您需要确保保持GCHandle活动状态。只有当GCHandle存在时,您获得的指针才会保持有效。