5

在 C# 项目中,我需要通过将引用放入结构中来传递对象参数。即我有一个结构传递给调度员

struct SOMESTRUCT
{
    public int lpObject;
}

其中 lpObject 包含一个指向自定义对象的指针,例如

class SomeClass
{
    private string foo;
}

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);

但是,我不知道如何从 lpObject 字段中检索 myObject 成员。像这样的东西:

SomeClass myObject = CastPointerToObject(struct.myRef) as SomeClass;

有没有办法做到这一点,还是不可能?如何告诉垃圾收集器处理对象?我应该创建一个新的垃圾收集对象并逐个字段复制数据吗?

蒂亚,

4

2 回答 2

5

不不不不 !!!

struct SOMESTRUCT
{
    public SomeClass object_ref;
}

是在结构中存储引用的正确方法。

您编写的代码和接受的答案是 100% 损坏的。

返回的地址只有在完好无损GC.AddrOfPinnedObject(GCHandle)时才有效。GCHandle你不能打电话GCHandle.Free,你不能让GCHandle被收集。在您的代码中,地址在您存储时已经毫无意义。

但是您应该让 .NET 在垃圾收集期间通过使用引用类型的变量来管理指针。那么你就不需要跳过篮球了。获取托管对象地址的唯一原因是将其传递给现有的本地 DLL 函数,该函数将在返回后保存指针。例如,OpenGL 缓冲区数组是必需的。在调用其他 C# 方法时,从来没有必要。

如果 SOMESTRUCT 实际上是您未提及的某些 DLL 函数使用的本机数据类型,那么您需要确保保持GCHandle活动状态。只有GCHandle存在,您获得的指针才会保持有效。

于 2011-01-15T17:08:32.337 回答
2

您的意思是要将返回的指针转换回结构吗?

如同:

lvHitTestInfo = (LVHITTESTINFO)Marshal.PtrToStructure(lP, typeof(LVHITTESTINFO));

其中 lvHitTestInfo 是一个结构,而 lp 是一个指针。

或者我没有正确理解你的问题。也许您可以解释更多(更完整的代码示例)。

于 2010-06-29T14:36:53.283 回答