Как утверждают большинство людей, вы можете использовать для этого фиксированный или BitConverter. Но в основном нет. Если вам нужны данные на маршале, .NET сделает это за вас. В большинстве случаев вы не хотите передавать ссылки на управляемую память неуправляемым функциям (поскольку вы не будете иметь никакого контроля над состоянием данных или ссылок)
«Исправлено» гарантирует, что данные не будут перемещены или освобождены сборщиком мусора в пределах области действия, и вы получите указатель. Однако за пределами фиксированного блока неуправляемый код все еще может иметь этот указатель, даже если указатель мог быть признан недействительным сборщиком мусора, что быстро приведет к сбою приложения без какой-либо очевидной причины.
В .NET вы редко получаете какое-либо благоприятное повышение производительности за счет использования небезопасного кода, и передача ссылок на управляемые данные в неуправляемый код не всегда благоприятна.
Но есть несколько ответов:
byte value = 255;
unsafe
{
byte* ptr = &value; // Assign the address of value to ptr
SomeUnsafeCode(ptr);
}
Вам не нужно использовать фиксированные в стеке переменные, поскольку они не являются сборщиком мусора.
Для переменных, собираемых мусором, вам нужно исправить:
byte[] array = SomeGenerator();
unsafe
{
fixed(byte* ptr = array)
{
SomeUnsafeCode(ptr);
}
}
Это прикрепит массив к памяти, так что сборщик мусора не будет касаться массива, пока он исправлен.
Иногда вам захочется закрепить данные на нескольких блоках кода. В этом случае вы хотели бы использовать System.Runtime.InteropServices.GCHandle
.