다음을 통해 공유


방법: P/Invoke를 사용하여 배열 마샬링

.NET Framework Platform Invoke(P/Invoke) 지원을 사용할 때 CLR 문자열 형식 String 을 사용하여 C 스타일 문자열을 허용하는 네이티브 함수를 호출할 수 있습니다. 가능한 경우 P/Invoke 대신 C++ Interop 기능을 사용하는 것이 좋습니다. P/Invoke는 컴파일 시간 오류 보고를 거의 제공하지 않으며 형식이 안전하지 않으며 구현하는 데 지루할 수 있습니다. 관리되지 않는 API가 DLL로 패키지되고 소스 코드를 사용할 수 없는 경우 P/Invoke가 유일한 옵션입니다. 그렇지 않으면 C++ Interop 사용(암시적 P/Invoke)을 참조하세요.

예시

네이티브 배열과 관리되는 배열은 메모리에 다르게 배치되므로 관리/관리되지 않는 경계를 성공적으로 통과하려면 변환 또는 마샬링이 필요합니다. 이 문서에서는 관리 코드에서 단순(블릿 가능) 항목의 배열을 네이티브 함수에 전달하는 방법을 보여 줍니다.

일반적으로 관리/관리되지 않는 데이터 마샬링의 경우와 마찬가지로 이 DllImportAttribute 특성은 사용되는 각 네이티브 함수에 대한 관리되는 진입점을 만드는 데 사용됩니다. 배열을 인수 MarshalAsAttribute 로 사용하는 함수에서 특성을 사용하여 데이터를 마샬링하는 방법을 지정해야 합니다. 다음 예제 UnmanagedType 에서 열거형은 관리되는 배열이 C 스타일 배열로 마샬링됨을 나타내는 데 사용됩니다.

다음 코드는 관리되지 않는 모듈과 관리되는 모듈로 구성됩니다. 관리되지 않는 모듈은 정수 배열을 허용하는 함수를 정의하는 DLL입니다. 두 번째 모듈은 이 함수를 가져오지만 관리되는 배열을 기준으로 정의하는 관리되는 명령줄 애플리케이션입니다. 이 특성은 MarshalAsAttribute 호출될 때 배열을 네이티브 배열로 변환하도록 지정하는 데 사용됩니다.

// TraditionalDll4.cpp
// compile with: /LD /EHsc
#include <iostream>

#define TRADITIONALDLL_EXPORTS
#ifdef TRADITIONALDLL_EXPORTS
#define TRADITIONALDLL_API __declspec(dllexport)
#else
#define TRADITIONALDLL_API __declspec(dllimport)
#endif

extern "C" {
   TRADITIONALDLL_API void TakesAnArray(int len, int[]);
}

void TakesAnArray(int len, int a[]) {
   printf_s("[unmanaged]\n");
   for (int i=0; i<len; i++)
      printf("%d = %d\n", i, a[i]);
}

관리되는 모듈은 .를 사용하여 /clr컴파일됩니다.

// MarshalBlitArray.cpp
// compile with: /clr
using namespace System;
using namespace System::Runtime::InteropServices;

value struct TraditionalDLL {
   [DllImport("TraditionalDLL4.dll")]
   static public void TakesAnArray(
   int len,[MarshalAs(UnmanagedType::LPArray)]array<int>^);
};

int main() {
   array<int>^ b = gcnew array<int>(3);
   b[0] = 11;
   b[1] = 33;
   b[2] = 55;
   TraditionalDLL::TakesAnArray(3, b);

   Console::WriteLine("[managed]");
   for (int i=0; i<3; i++)
      Console::WriteLine("{0} = {1}", i, b[i]);
}

DLL의 어떤 부분도 기존 #include 지시문을 통해 관리 코드에 노출되지 않습니다. 실제로 DLL은 런타임에만 액세스되므로 컴파일 시간에 사용하여 DllImportAttribute 가져온 함수의 문제를 검색할 수 없습니다.

참고 항목

C++에서 명시적 P/Invoke 사용(DllImport 특성)