Поделиться через


Маршалинг по умолчанию для делегатов

Управляемый делегат маршалируется как COM-интерфейс или как указатель на функцию, используя следующий механизм вызовов:

  • Для вызова неуправляемого кода делегат по умолчанию маршалируется как указатель на функцию.

  • Для COM-взаимодействия делегат по умолчанию маршалируется как COM-интерфейс типа _Delegate. Интерфейс _Delegate определяется в библиотеке типов Mscorlib.tlb и содержит метод Delegate.DynamicInvoke, позволяющий вызывать метод, на который ссылается делегат.

В следующей таблице показаны варианты маршалинга для типа данных управляемого делегата. Атрибут MarshalAsAttribute предоставляет несколько значений перечисления UnmanagedType для выполнения маршалинга делегатов.

Тип перечисления

Описание неуправляемого формата

UnmanagedType.FunctionPtr

Указатель на неуправляемую функцию.

UnmanagedType.Interface

Интерфейс типа _Delegate, определенный в Mscorlib.tlb.

Рассмотрим следующий пример кода, в котором методы интерфейса DelegateTestInterface экспортируются в библиотеку COM-типов. Обратите внимание, что только делегаты, помеченные ключевым словом ref (или ByRef), передаются как параметры In/Out.

using System;
using System.Runtime.InteropServices;

public interface DelegateTest {
void m1(Delegate d);
void m2([MarshalAs(UnmanagedType.Interface)] Delegate d);   
void m3([MarshalAs(UnmanagedType.Interface)] ref Delegate d);  
void m4([MarshalAs(UnmanagedType.FunctionPtr)] Delegate d); 
void m5([MarshalAs(UnmanagedType.FunctionPtr)] ref Delegate d);   
}

Представление библиотеки типов

importlib("mscorlib.tlb");
interface DelegateTest : IDispatch {
[id(…)] HRESULT m1([in] _Delegate* d);
[id(…)] HRESULT m2([in] _Delegate* d);
[id(…)] HRESULT m3([in, out] _Delegate** d);
[id()] HRESULT m4([in] int d);
[id()] HRESULT m5([in, out] int *d);
   };

Указатель на функцию может быть разыменован, точно так же как может быть разыменован любой другой указатель на неуправляемую функцию.

ПримечаниеПримечание

Ссылка на указатель на функцию в управляемом делегате, хранимая в неуправляемом коде, не препятствует выполнению средой CLR сборки мусора для управляемого объекта.

Например, следующий код некорректен, потому что ссылка на объект cb, переданная в метод SetChangeHandler, не сохраняет объект cb в активном состоянии по окончании жизненного цикла метода Test. После применения к объекту cb процедуры сборки мусора указатель на функцию, переданный в SetChangeHandler, становится недействительным.

public class ExternalAPI {
   [DllImport("External.dll")]
   public static extern void SetChangeHandler(
      [MarshalAs(UnmanagedType.FunctionPtr)]ChangeDelegate d);
}
public delegate bool ChangeDelegate([MarshalAs(UnmanagedType.LPWStr) string S);
public class CallBackClass {
   public bool OnChange(string S){ return true;}
}
internal class DelegateTest {
   public static void Test() {
      CallBackClass cb = new CallBackClass();
      // Caution: The following reference on the cb object does not keep the 
      // object from being garbage collected after the Main method 
      // executes.
      ExternalAPI.SetChangeHandler(new ChangeDelegate(cb.OnChange));   
   }
}

Чтобы компенсировать неожиданную сборку мусора, вызывающий объект должен гарантировать, что объект cb будет находиться в активном состоянии до тех пор, пока используется указатель на неуправляемую функцию. При необходимости можно, как показано в следующем примере, настроить для неуправляемого кода передачу в управляемый код уведомлений о том, что указатель на функцию больше не требуется.

internal class DelegateTest {
   CallBackClass cb;
   // Called before ever using the callback function.
   public static void SetChangeHandler() {
      cb = new CallBackClass();
      ExternalAPI.SetChangeHandler(new ChangeDelegate(cb.OnChange));
   }
   // Called after using the callback function for the last time.
   public static void RemoveChangeHandler() {
      // The cb object can be collected now. The unmanaged code is 
      // finished with the callback function.
      cb = null;
   }
}

См. также

Основные понятия

Преобразуемые и непреобразуемые типы

Атрибуты направления

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

Другие ресурсы

Поведение маршалинга по умолчанию