Передача данных между управляемым и неуправляемым кодом
При передаче данных между управляемым и неуправляемым кодом необходимо учитывать, как данные хранятся и управляются в памяти. В этом разделе объясняется, как передавать данные между управляемым и неуправляемым кодом в Unity.
При передаче данных между функциями параметры и возвращаемые значения могут быть скопированы в стек или храниться в куче. Стек обычно используется для типов значений, и данные сохраняются в течение вызова функции. Данные с менее предсказуемым сроком жизни хранятся в куче. В C# время выполнения скрипта управляет кучей, что включает в себя перемещение данных и высвобождение памяти, которая больше не используется. В неуправляемом коде вы напрямую запрашиваете и управляете памятью кучи.
Когда вы вызываете неуправляемую функцию из управляемого кода или управляемую функцию из неуправляемого кода, обе стороны могут напрямую получить доступ к данным стека. Поэтому вы можете передавать небольшие типы значений, такие как float и int, без дополнительных мер предосторожности. Вам не нужно беспокоиться о том, что данные исчезнут до того, как другая сторона вызова получит к ним доступ.
Однако при передаче типов ссылок и более крупных типов значений, таких как строки, массивы и некоторые структуры, данные могут храниться в куче. В этом случае между управляемым и неуправляемым кодом передается только ссылка или указатель. Необходимо обеспечить, чтобы данные оставались в одном и том же месте памяти до тех пор, пока к ним можно получить доступ.
На протяжении обычного вызова в неуправляемый код, время выполнения сценария обрабатывает это за вас. В качестве части маршрутизации, оно сохраняет соответствующие управляемые данные живыми и на месте до возвращения вызова. Вам нужно только принять дополнительные меры для расширенных сценариев, когда неуправляемый код сохраняет ссылку на данные и доступ к ним после возвращения вызова, такие как асинхронный обратный вызов или указатель, который основной код хранит для последующего использования. В этих случаях вы можете использовать структуру GCHandle для "прикрепления" объекта в памяти. Время выполнения сценария не будет перемещать или освобождать прикрепленный объект, пока вы не удалите GCHandle.
//Create a GCHandle to pin data in memory
GCHandle handle = GCHandle.Alloc(yourObject, GCHandleType.Pinned);
//... pass data to unmanaged code that retains it beyond the call ...
handle.Free(); //Dispose of the handle when unmanaged code is finished
Примеры передачи различных типов данных см. в следующих разделах:
| Тема | Описание |
|---|---|
| Примитивные типы | Как передавать примитивные типы значений, такие как int, float и char. |
| Структуры, классы и союзы | Как передавать сложные типы. |
| NativeArrays | Как передавать NativeArray объекты. |
| Струны | Как передавать строковые объекты. |