CLI / C ++: void * to System :: Object - PullRequest
       27

CLI / C ++: void * to System :: Object

4 голосов
/ 01 августа 2011

Этот вопрос похож на этот пост , который я не смог использовать для решения своей проблемы. Я включил сюда некоторый код, который, надеюсь, поможет кому-то принести домой сообщение, к которому пришло другое сообщение.

Я хочу написать метод CLI / C ++, который может принимать указатель void в качестве параметра и возвращать управляемый объект (тип которого я знаю), на который он указывает. У меня есть управляемая структура:

public ref struct ManagedStruct { double a; double b;};

Метод, который я пытаюсь написать, который принимает пустой указатель на управляемую структуру в качестве параметра и возвращает структуру.

ManagedStruct^ VoidPointerToObject(void* data)
{   
    Object^ result = Marshal::PtrToStructure(IntPtr(data), Object::typeid);
    return (ManagedStruct^)result;
}

Метод вызывается здесь:

int main(array<System::String ^> ^args)
{   
    // The instance of the  managed type is created:
    ManagedStruct^ myData = gcnew ManagedStruct();
    myData->a = 1;  myData->b = 2;      

    // Suppose there was a void pointer that pointed to this managed struct
    void* voidPtr = &myData;

    //A method to return the original struct from the void pointer
    Object^ result = VoidPointerToObject(voidPtr);  
    return 0;
}

Сбой в методе VoidPointerToObject при вызове PtrToStructure с ошибкой: Указанная структура должна быть blittable или иметь информацию о компоновке

Я знаю, что это странно, но с такой ситуацией я сталкивался несколько раз, особенно когда неуправляемый код вызывает обратный вызов для управляемого кода и передает в качестве параметра void *.

1 Ответ

13 голосов
/ 01 августа 2011

(оригинальное объяснение ниже)

Если вам нужно передать управляемый дескриптор как void* через собственный код, вы должны использовать

void* voidPtr = GCHandle::ToIntPtr(GCHandle::Alloc(o)).ToPointer();

// ...

GCHandle h = GCHandle::FromIntPtr(IntPtr(voidPtr));
Object^ result = h.Target;
h.Free();

(или используйте вспомогательный класс C ++ / CLI gcroot)


Marshal::PtrToStructure, работающий с типами значений .

В C ++ / CLI это означает value class или value struct.Вы используете ref struct, который является ссылочным типом , несмотря на использование ключевого слова struct.

Связанная проблема:

void* voidPtr = &myData;

не указываетк объекту он указывает на дескриптор.

Чтобы создать собственный указатель на данные в управляемой куче, необходимо использовать закрепление.По этой причине преобразование между void* и Object^ не так полезно, как предполагает первый взгляд.

...