다음을 통해 공유


플랫폼 호출 래퍼 예제

업데이트: 2007년 11월

구조체에 단순 형식이 포함된 경우에는 개체를 네이티브 함수에 전달할 수 있으며, 이 경우 네이티브 루틴은 .NET Compact Framework에서 구조체를 압축하는 방식을 따라야 합니다.

매개 변수, 구조체에 대한 포인터를 하나씩 사용하는 DoRequest라는 네이티브 함수가 있다고 가정합니다. 구조체는 다음과 같은 필드 두 개를 정의합니다.

  • NULL로 끝나는 ANSI 문자열이 포함된 문자 배열

  • 정수

다음은 C++의 구조체입니다.

typedef struct 
{
    char *RequestName,
    int   Count,
} ALERT_REQUEST;

int DoAlertRequest(ALERT_REQUEST *pRequest);

C#에서 이 구조체의 관리되는 버전은 다음과 같습니다.

struct AlertRequest
{
    String RequestName;
    int    Count;
}

class AlertClass
{
    [DLLImport("ALERT.DLL", EntryPoint="DoAlertRequest", 
        CharSet=CharacterSet.Ansi)]
    public static extern int DoRequest(ref AlertRequest Req);
}

DllImportAttribute 특성은 네이티브 메서드 호출의 메타데이터를 나타내며, DoRequest 메서드의 위치(ALERT.DLL), 메서드의 이름(DoAllertRequest) 및 문자열을 ANSI로 마샬링(관리 코드의 모든 문자열은 유니코드임)해야 함을 공용 언어 런타임에 알립니다.

.NET Framework에서 C++를 사용하는 경우 이 메서드에 대한 호출은 다음과 같습니다.

AlertRequest Request = new AlertRequest()
Request.RequestName = "beep";
Request.Count = 10;
AlertClass.DoRequest(ref Request);

.NET Framework의 공용 언어 런타임에서는 DoRequest 호출을 발견하면 ALERT.DLL을 동적으로 로드하고 DoAlertRequest의 주소를 가져온 다음 필요에 따라 문자열을 변환하여 구조체의 관리되지 않는 버전을 빌드합니다. 그런 후에 이 구조체에 포인터를 푸시하고 DoAlertRequest를 호출합니다. 이 구조체에는 포함 String 개체가 들어 있기 때문에 구조체에 대한 포인터를 전달할 수 없습니다.

이러한 제약 조건을 고려할 때 네이티브 DoRequest 메서드를 직접 호출할 수 없으며 썽킹 호출을 대신 사용하여 DoRequest를 래핑해야 합니다. 다음은 C# 코드 예제입니다.

class AlertClass
{
    [DllImport("ALERT.DLL", EntryPoint="DoAlertRequestThunk")]
    private static extern int DoRequestThunk(String RequestName, int Count);

    public static int DoRequest(ref AlertRequst Req)
        {
            return DoRequestThunk(Req.RequestName, Req.Count);
        }
}

AlertClass에는 .NET Framework에서 상응하는 클래스와 시그니처가 같은 메서드가 포함됩니다. .NET Compact Framework의 DoRequest는 전용 네이티브 루틴을 호출하는 관리되는 루틴입니다. 위의 코드 예제에서 구조체 내의 String 개체는 마샬링될 수 없으므로 네이티브 루틴에 대한 호출에 대해 구조체의 각 필드가 별도의 인수로 분리됩니다. 썽크는 네이티브 DoRequest를 래핑하며 구조체의 관리되지 않는 버전을 빌드하고 문자열 변환을 수행합니다(아래의 C++ 코드 참조).

int DoRequestThunk(wchar_t *RequestNameW, int Count)
{
    ALERT_REQUEST Req;
    int ReturnCode;
       
    // CreateAnsiFromUnicodeString allocates and builds an ANSI
    // version of the Unicode string.
    Req.RequestName = CreateAnsiFromUnicodeString(RequestNameW);
    if (Req.RequestName == NULL) 
        Return 0;

    Req.Count = Count;

    // This is the native DoRequest, not to be confused
    // with the managed method of the same name.
    ReturnCode = DoAlertRequest(&Req);

    free(Req.RequestName)
    return ReturnCode;
}

참고 항목

기타 리소스

플랫폼 호출 지원