Преобразование из void * в объект в C # - PullRequest
5 голосов
/ 29 июня 2010

В проекте 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);

Однако я не могу понять, как извлечь элементы myObject из полей lpObject. Примерно так:

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

Есть ли способ сделать это или это невозможно? Как я могу сказать сборщику мусора обработать объект? Должен ли я создать новый объект для сбора мусора и скопировать поле данных по полю?

TYIA

Ответы [ 2 ]

4 голосов
/ 15 января 2011

нет Нет НЕТ НЕТ НЕТ !!!

Это

struct SOMESTRUCT
{
    public SomeClass object_ref;
}

Правильный способ хранения ссылки в структуре.

Код, который вы написали, и принятый ответ нарушены на 100%.

Адрес, возвращаемый GC.AddrOfPinnedObject(GCHandle), действителен только тогда, когда GCHandle не поврежден.Вы не должны звонить GCHandle.Free, и вы не должны позволять GCHandle быть собранным.В вашем коде адрес уже не имеет смысла к тому времени, когда вы сохраняете его.

Но вы должны просто позволить .NET позаботиться об управлении указателем во время сборки мусора, используя переменную ссылочного типа.Тогда вам не нужно прыгать через обручи.Единственная причина получить адрес управляемого объекта - это передать его в существующую встроенную функцию DLL, которая сохранит указатель после его возврата.Например, это необходимо для буферных массивов OpenGL.Это НЕ обязательно, когда-либо при вызове других методов C #.

Если SOMESTRUCT на самом деле является собственным типом данных, используемым некоторой функцией DLL, о которой вы не упомянули, то вам нужно убедиться, что GCHandle жив.Только до тех пор, пока существует GCHandle, указатель, который вы получили, останется действительным.

2 голосов
/ 29 июня 2010

Вы имеете в виду, что хотите привести возвращенный указатель обратно к структуре?

Похоже на:

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

Где lvHitTestInfo - это структура, а lp указатель.

Или я не правильно понял ваш вопрос.Может быть, вы можете объяснить больше (более полный пример кода).

...