C++ Interop 사용(암시적 PInvoke)

다른 .NET 언어와 달리 Visual C++는 관리 코드와 관리되지 않는 코드가 동일한 애플리케이션 및 동일한 파일( 관리되는 비관리 형 pragma)에 존재할 수 있도록 하는 상호 운용성 지원을 제공합니다. 이렇게 하면 Visual C++ 개발자가 나머지 애플리케이션을 방해하지 않고 .NET 기능을 기존 Visual C++ 애플리케이션에 통합할 수 있습니다.

dllexport, dllimport를 사용하여 관리되는 컴파일랜드에서 관리되지 않는 함수를 호출할 수도 있습니다.

암시적 PInvoke는 함수 매개 변수를 마샬링하는 방법 또는 DllImportAttribute를 명시적으로 호출할 때 지정할 수 있는 다른 세부 정보를 지정할 필요가 없는 경우에 유용합니다.

Visual C++는 관리되는 함수와 관리되지 않는 함수가 상호 운용하는 두 가지 방법을 제공합니다.

명시적 PInvoke는 .NET Framework에서 지원되며 대부분의 .NET 언어에서 사용할 수 있습니다. 그러나 이름에서 알 수 있듯이 C++ Interop은 Visual C++와 관련이 있습니다.

C++ Interop

C++ Interop은 더 나은 형식 안전성을 제공하며 일반적으로 구현하기가 덜 지루합니다. 그러나 C++ Interop은 관리되지 않는 소스 코드를 사용할 수 없거나 플랫폼 간 프로젝트에 사용할 수 없는 경우 옵션이 아닙니다.

C++ COM Interop

Visual C++에서 지원하는 상호 운용성 기능은 COM 구성 요소와 상호 운용할 때 다른 .NET 언어보다 특정한 이점을 제공합니다. C++ Interop은 데이터 형식에 대한 제한된 지원 및 모든 COM 인터페이스의 모든 멤버에 대한 필수 노출과 같은 .NET Framework Tlbimp.exe(형식 라이브러리 가져오기)의 제한으로 제한되는 대신 COM 구성 요소에 의지하여 액세스할 수 있으며 별도의 interop 어셈블리가 필요하지 않습니다. Visual Basic 및 C#과 달리 Visual C++는 일반적인 COM 메커니즘(예: CoCreateInstanceQueryInterface)을 사용하여 COM 개체를 직접 사용할 수 있습니다. 이는 컴파일러가 자동으로 전환 코드를 삽입하여 관리되는 함수에서 관리되지 않는 함수로 다시 이동하게 하는 C++ Interop 기능으로 인해 가능합니다.

C++ Interop를 사용하면 COM 구성 요소가 일반적으로 사용되거나 C++ 클래스 내에 래핑될 수 있으므로 사용할 수 있습니다. 이러한 래퍼 클래스를 사용자 지정 런타임 호출 가능 래퍼 또는 CRCW라고 하며 애플리케이션 코드에서 COM을 직접 사용하는 경우보다 두 가지 이점이 있습니다.

  • 결과 클래스는 Visual C++가 아닌 언어에서 사용할 수 있습니다.

  • COM 인터페이스의 세부 정보는 관리되는 클라이언트 코드에서 숨길 수 있습니다. .NET 데이터 형식은 네이티브 형식 대신 사용할 수 있으며 CRCW 내에서 데이터 마샬링의 세부 정보를 투명하게 수행할 수 있습니다.

COM이 직접 사용되는지 CRCW를 통해 사용되는지에 관계없이 단순 Blittable 형식이 아닌 인수 형식을 마샬링해야 합니다.

Blittable 형식

단순하고 내장 형식(Blittable 및 Blittable이 아닌 형식 참조)을 사용하는 관리되지 않는 API의 경우 이러한 데이터 형식은 메모리에서 동일한 표현을 가지지만 더 복잡한 데이터 형식에는 명시적 데이터 마샬링이 필요하기 때문에 특별한 코딩이 필요하지 않습니다. 예를 들어 방법: PInvoke를 사용하여 관리 코드에서 네이티브 DLL 호출을 참조하세요.

예시

// vcmcppv2_impl_dllimp.cpp
// compile with: /clr:pure user32.lib
using namespace System::Runtime::InteropServices;

// Implicit DLLImport specifying calling convention
extern "C" int __stdcall MessageBeep(int);

// explicit DLLImport needed here to use P/Invoke marshalling because
// System::String ^ is not the type of the first parameter to printf
[DllImport("msvcrt.dll", EntryPoint = "printf", CallingConvention = CallingConvention::Cdecl,  CharSet = CharSet::Ansi)]
// or just
// [DllImport("msvcrt.dll")]
int printf(System::String ^, ...);

int main() {
   // (string literals are System::String by default)
   printf("Begin beep\n");
   MessageBeep(100000);
   printf("Done\n");
}
Begin beep
Done

섹션 내용

interop 시나리오에서 대리자를 사용하는 방법에 대한 자세한 내용은 대리자(C++ 구성 요소 확장)를 참조하세요.

참고 항목