Копирование и закреплениеCopying and Pinning

При маршалировании данных маршалер может копировать или закреплять включаемые в процесс данные.When marshaling data, the interop marshaler can copy or pin the data being marshaled. В ходе этого процесса копия данных переносится из одного расположения в памяти в другое.Copying the data places a copy of data from one memory location in another memory location. На следующем рисунке показаны различия между копированием типа значения и типа, передаваемого по ссылке, из управляемой памяти в неуправляемую.The following illustration shows the differences between copying a value type and copying a type passed by reference from managed to unmanaged memory.

Схема, на которой показано, как копируются тип значения и ссылочный тип.

Аргументы метода, передаваемые по значению, маршалируются в неуправляемый код как значения в стеке.Method arguments passed by value are marshaled to unmanaged code as values on the stack. Процесс копирования является прямым.The copying process is direct. Аргументы, передаваемые по ссылке, передаются как указатели на стек.Arguments passed by reference are passed as pointers on the stack. Ссылочные типы также могут передаваться по значению и по ссылке.Reference types are also passed by value and by reference. Как показано на следующем рисунке, ссылочные типы, передаваемые по значению, либо копируются, либо закрепляются.As the following illustration shows, reference types passed by value are either copied or pinned:

Схема, на которой показаны ссылочные типы, передаваемые по значению и по ссылке.

При закреплении данные временно блокируются в текущем положении в памяти, в результате чего исключается их перемещение стандартным сборщиком мусора общеязыковой среды выполнения.Pinning temporarily locks the data in its current memory location, thus keeping it from being relocated by the common language runtime's garbage collector. Маршалер закрепляет данные, чтобы сократить затраты ресурсов на копирование и повысить производительность.The marshaler pins data to reduce the overhead of copying and enhance performance. Копирование или закрепление данных в рамках процесса маршалинга осуществляется в зависимости от типа этих данных.The type of the data determines whether it is copied or pinned during the marshaling process. Закрепление автоматически выполняется во время маршалинга для таких объектов, как String. Также их можно закрепить вручную с использованием класса GCHandle.Pinning is automatically performed during marshaling for objects such as String, however you can also manually pin memory using the GCHandle class.

Форматированные непреобразуемые классыFormatted Blittable Classes

Форматированные непреобразуемые классы имеют фиксированную структуру (форматирование) и общее представление данных как в управляемой, так и в неуправляемой памяти.Formatted blittable classes have fixed layout (formatted) and common data representation in both managed and unmanaged memory. Если требуется выполнить маршалинг таких типов, вызываемому объекту напрямую передается указатель на объект в куче.When these types require marshaling, a pointer to the object in the heap is passed to the callee directly. Вызываемый объект может изменять содержимое в расположении в памяти, на которое ссылается указатель.The callee can change the contents of the memory location being referenced by the pointer.

Примечание

Вызываемый метод может изменять содержимое памяти в том случае, если параметр помечен как параметр вывода или как параметр ввода-вывода. Напротив, вызываемый объект не должен изменять содержимое памяти, если параметр помечен для маршалинга как параметр ввода (по умолчанию для форматированных непреобразуемых типов).The callee can change the memory contents if the parameter is marked Out or In/Out. In contrast, the callee should avoid changing the contents when the parameter is set to marshal as In, which is the default for formatted blittable types. Если объект ввода изменяется, это может привести к проблемам при экспорте того же класса в библиотеку типов и его использовании для выполнения вызовов между подразделениями.Modifying an In object generates problems when the same class is exported to a type library and used to make cross-apartment calls.

Форматированные преобразуемые классыFormatted Non-Blittable Classes

Форматированные преобразуемые классы имеют фиксированную структуру (форматирование), но разное представление данных в управляемой и неуправляемой памяти.Formatted non-blittable classes have fixed layout (formatted) but the data representation is different in managed and unmanaged memory. В следующих ситуациях может потребоваться преобразование данных:The data can require transformation under the following conditions:

  • Если преобразуемый класс маршалируется по значению, вызываемый объект получает указатель на копию структуры данных.If a non-blittable class is marshaled by value, the callee receives a pointer to a copy of the data structure.

  • Если преобразуемый класс маршалируется по ссылке, вызываемый объект получает указатель на указатель на копию структуры данных.If a non-blittable class is marshaled by reference, the callee receives a pointer to a pointer to a copy of the data structure.

  • Если установлен атрибут InAttribute, для инициализации этой копии всегда используется состояние экземпляра и при необходимости выполняется маршалинг.If the InAttribute attribute is set, this copy is always initialized with the instance's state, marshaling as necessary.

  • Если установлен атрибут OutAttribute, состояние всегда копируется обратно в экземпляр при возврате и при необходимости выполняется маршалинг.If the OutAttribute attribute is set, the state is always copied back to the instance on return, marshaling as necessary.

  • Если установлены одновременно атрибуты InAttribute и OutAttribute, обе операции копирования выполняются обязательно.If both InAttribute and OutAttribute are set, both copies are required. Если один из атрибутов опущен, в целях оптимизации маршалер может исключить другую операцию копирования.If either attribute is omitted, the marshaler can optimize by eliminating either copy.

Ссылочные типыReference Types

Ссылочные типы могут передаваться по значению или по ссылке.Reference types can be passed by value or by reference. При передаче по значению в стек передается указатель на тип.When they are passed by value, a pointer to the type is passed on the stack. При передаче по ссылке в стек передается указатель на указатель на тип.When passed by reference, a pointer to a pointer to the type is passed on the stack.

Ссылочные типы имеют следующие условные характеристики:Reference types have the following conditional behavior:

  • Если ссылочный тип передается по значению и содержит члены преобразуемых типов, типы преобразуются дважды:If a reference type is passed by value and it has members of non-blittable types, the types are converted twice:

    • Когда аргумент передается в неуправляемый код.When an argument is passed to the unmanaged side.

    • При возврате из вызова.On return from the call.

    Чтобы исключить лишние операции копирования и преобразования, эти типы маршалируются как параметры ввода.To avoid unnecessarily copying and conversion, these types are marshaled as In parameters. Чтобы вызывающий объект мог видеть изменения, выполненные вызывающим объектом, необходимо явно применить атрибуты InAttribute и OutAttribute к аргументу.You must explicitly apply the InAttribute and OutAttribute attributes to an argument for the caller to see changes made by the callee.

  • Если ссылочный тип передается по значению и содержит только члены непреобразуемых типов, он может быть закреплен в процессе маршалирования, а любые изменения членов типа, выполненные вызываемым объектом, будут видны вызывающему объекту.If a reference type is passed by value and it has only members of blittable types, it can be pinned during marshaling and any changes made to the members of the type by the callee are seen by the caller. Чтобы реализовать такое поведение, явно примените атрибуты InAttribute и OutAttribute.Apply InAttribute and OutAttribute explicitly if you want this behavior. Без этих атрибутов направления маршалер взаимодействия не экспортирует информацию о направлении в библиотеку типов (экспортируется как параметр ввода, то есть реализуется поведение по умолчанию), что может вызвать проблемы с маршалингом COM между подразделениями.Without these directional attributes, the interop marshaler does not export directional information to the type library (it exports as In, which is the default) and this can cause problems with COM cross-apartment marshaling.

  • Если ссылочный тип передается по ссылке, он будет по умолчанию маршалироваться как параметр ввода-вывода.If a reference type is passed by reference, it will be marshaled as In/Out by default.

System.String и System.Text.StringBuilderSystem.String and System.Text.StringBuilder

При маршалинге данных в неуправляемый код по значению или по ссылке маршалер обычно копирует данные во вторичный буфер (в процессе копирования может выполняться преобразование кодировки) и передает вызываемому объекту ссылку на буфер.When data is marshaled to unmanaged code by value or by reference, the marshaler typically copies the data to a secondary buffer (possibly converting character sets during the copy) and passes a reference to the buffer to the callee. Если ссылка не является объектом BSTR (для выделения используется SysAllocString), выделение памяти всегда осуществляется с помощью CoTaskMemAlloc.Unless the reference is a BSTR allocated with SysAllocString, the reference is always allocated with CoTaskMemAlloc.

В целях оптимизации при маршалинге строк любого типа по значению (например, строка символов Юникода) маршалер передает вызываемому объекту прямой указатель на управляемые строки во внутреннем буфере Юникода вместо копирования в новый буфер.As an optimization when either string type is marshaled by value (such as a Unicode character string), the marshaler passes the callee a direct pointer to managed strings in the internal Unicode buffer instead of copying it to a new buffer.

Внимание!

Если строка передается по значению, вызываемый объект не должен изменять ссылку, передаваемую маршалером.When a string is passed by value, the callee must never alter the reference passed by the marshaler. Это может привести к повреждению управляемой кучи.Doing so can corrupt the managed heap.

Если System.String передается по ссылке, маршалер копирует содержимое строки во вторичный буфер, прежде чем выполнять вызов.When a System.String is passed by reference, the marshaler copies the contents the string to a secondary buffer before making the call. После этого содержимое буфера копируется в новую строку при возврате из вызова.It then copies the contents of the buffer into a new string on return from the call. Такой подход гарантирует, что неизменяемая управляемая строка останется без изменений.This technique ensures that the immutable managed string remains unaltered.

Если System.Text.StringBuilder передается по значению, маршалер передает ссылку на внутренний буфер StringBuilder напрямую вызывающему объекту.When a System.Text.StringBuilder is passed by value, the marshaler passes a reference to the internal buffer of the StringBuilder directly to the caller. Вызывающий и вызываемый объекты должны согласовывать размер буфера.The caller and callee must agree on the size of the buffer. Вызывающий объект отвечает за создание буфера StringBuilder соответствующей длины.The caller is responsible for creating a StringBuilder of adequate length. Вызываемый объект должен принимать необходимые меры предосторожности, чтобы предотвратить переполнение буфера.The callee must take the necessary precautions to ensure that the buffer is not overrun. StringBuilder является исключением из правила, согласно которому ссылочные типы, передаваемые по значению, по умолчанию передаются в виде параметра ввода.StringBuilder is an exception to the rule that reference types passed by value are passed as In parameters by default. Он всегда передается как параметр ввода-вывода.It is always passed as In/Out.

См. такжеSee also