다음을 통해 공유


방법: CRCW와 함께 네이티브 COM 서버 사용

업데이트: 2007년 11월

다른 .NET 언어와 달리 Visual C++에서는 COM 인터페이스를 비롯한 관리되지 않는 API에 직접 매끄럽게 액세스하는 데 필요한 interop 기능을 제공합니다. 특히 COM interop의 경우 이 기능을 사용하면 많은 이점을 얻을 수 있습니다.

예제

방법: TLBIMP와 함께 네이티브 COM 서버 사용에 나와 있는 예제와 마찬가지로 이 예제에서는 C:\window\System32 디렉터리에 있는 Quartz.dll에서 정의한 COM 인터페이스를 사용하여 AVI 파일을 재생합니다. 그러나 이 예제의 경우에는 Tlbimp.exe를 사용하여 생성된 별도의 interop 어셈블리 대신 C++ interop를 사용합니다. 이 방법을 사용하면 여러 가지 이점을 얻을 수 있습니다. 이 경우 interop 코드가 응용 프로그램으로 빌드되므로 별도의 어셈블리에 의존할 필요가 없습니다. 또한 노출되어 관리되는 인터페이스를 .NET에 더욱 적합하도록 사용자 지정할 수 있습니다. 예를 들어, RenderFile 메서드에서 char* 대신 System.String을 사용합니다. 관리되는 버전의 COM 인터페이스를 CRCW(사용자 지정 런타임 호출 가능 래퍼)라고 합니다.

CRCW를 작성하는 데 interop 어셈블리는 필요하지 않지만 COM 인터페이스를 정의하는 헤더 파일은 필요합니다. 형식 라이브러리가 포함된 COM 구성 요소의 경우 이러한 헤더는 MIDL Compiler를 사용하여 생성할 수 있습니다.

다음 코드 예제의 첫 번째 부분에서는 관리되는 응용 프로그램에 노출할 멤버를 노출하는 사용자 지정 래퍼를 정의합니다. 두 번째 부분은 사용자 지정 래퍼를 사용하여 AVI 파일을 재생하는 콘솔 응용 프로그램입니다.

유효한 AVI 파일의 이름을 사용하여 결과 .exe 파일을 실행하면 파일이 창에 렌더링됩니다.

// use_native_COM_servers_with_CRCWs.cpp
// compile with: /clr
// processor: x86
#include <comdef.h>
#import "quartz.tlb" no_namespace

using namespace System;
using namespace System::Runtime::InteropServices;

//_COM_SMARTPTR_TYPEDEF(IMediaControl, IID_IMediaControl);

ref struct Player : public IDisposable {
   Player() : fm((new IMediaControlPtr())) {
      fm->CreateInstance(__uuidof(FilgraphManager), 0, CLSCTX_INPROC_SERVER);
   if ((*fm) == 0)
      throw gcnew Exception("Could not create COM object");
   }

   ~Player() {
      this->!Player();
   }

   !Player() {
    (*fm).Release();
      delete fm;
   }

   void RenderFile(String^ file) {
      IntPtr ip = Marshal::StringToBSTR(file);
      BSTR b = static_cast<BSTR>(ip.ToPointer());
       (*fm)->RenderFile(b);
      Marshal::FreeBSTR(ip);
   }

   void Run() {
      (*fm)->Run();
   }

private:
   IMediaControlPtr* fm;
};
   
void DisplayUsage() { 
   Console::WriteLine("AVIPlayer2: Plays AVI files."); 
   Console::WriteLine("Usage: AVIPlayer2.EXE <filename>"); 
}

int main() { 
   array<String^>^ args = Environment::GetCommandLineArgs();

   if (args->Length != 2) {
      DisplayUsage();
      return 0;
   } 

   String^ filename = args[1]; 
   if (filename->Equals("/?")) {
      DisplayUsage();
      return 0;
   }

   Player^ player = gcnew Player;

   player->RenderFile(filename);
   player->Run();

   Console::WriteLine("press any key");
   Console::ReadLine();
}

참고 항목

참조

.NET에서 네이티브 COM 서버 사용