从void*转换为C#中的对象

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,

Ben*_*igt 5

否否否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存在时,您获得的指针才会保持有效。