다음을 통해 공유


대리자에 대한 기본 마샬링

관리되는 대리자는 호출하는 메커니즘에 따라 COM 인터페이스 또는 함수 포인터로 마샬링됩니다.

  • 플랫폼 호출의 경우 대리자는 기본적으로 관리되지 않는 함수 포인터로 마샬링됩니다.

  • COM interop의 경우 대리자는 기본적으로 _Delegate 형식의 COM 인터페이스로 마샬링됩니다. _Delegate 인터페이스는 Mscorlib.tlb 형식 라이브러리에 정의되어 있으며 대리자가 참조하는 메서드를 호출할 수 있도록 하는 Delegate.DynamicInvoke 메서드가 포함되어 있습니다.

다음 표에서는 관리되는 대리자 데이터 형식의 마샬링 옵션을 보여 줍니다. MarshalAsAttribute 특성은 대리자를 마샬링하기 위한 몇 개의 UnmanagedType 열거형 값을 제공합니다.

열거형

관리되지 않는 형식의 설명

UnmanagedType.FunctionPtr

관리되지 않는 함수 포인터

UnmanagedType.Interface

Mscorlib.tlb에 정의된 _Delegate 형식의 인터페이스

다음 예제 코드에서는 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);
   };

함수 포인터는 다른 관리되지 않는 함수 포인터와 마찬가지로 역참조될 수 있습니다.

참고참고

비관리 코드에 포함된 관리되는 대리자에 대한 함수 포인터를 참조해도 공용 언어 런타임에서는 관리되는 개체에 대한 가비지 수집을 수행할 수 있습니다.

예를 들어, 다음 코드에서는 cb 개체에 대한 참조가 SetChangeHandler 메서드에 전달되면 Test 메서드의 범위를 벗어나므로 cb가 유효하지 않습니다. 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;
   }
}

참고 항목

개념

Blittable 형식 및 비 Blittable 형식

방향 특성

복사 및 고정

기타 리소스

기본 마샬링 동작