Поделиться через


Практическое руководство. Использование встроенных серверов COM с CRCW

Обновлен: Ноябрь 2007

В отличие от других языков .NET Visual C++ предоставляет функции взаимодействия, которые позволяют прямо и эффективно получить доступ к неуправляемым функциям API, включая COM-интерфейсы. В частности, для модели COM, это дает серьезные преимущества.

Пример

Подобно примеру в Практическое руководство. Использование неуправляемых COM-серверов с помощью средства TLBIMP, в этом примере использованы COM-интерфейсы, определенные в файле Quartz.dll (в каталоге C:\window\System32) для воспроизведения AVI-файлов. Однако в этом случае взаимодействие C++ использовано вместо отдельной сборки взаимодействия, созданной с помощью файла Tlbimp.exe. У этого метода есть несколько преимуществ. В этом случае код взаимодействия встроен в приложение, таким образом, нет зависимости от отдельной сборки. Также предоставленный управляемый интерфейс настроен так, чтобы быть более подобным .NET. Например, метод RenderFile принимает System.String вместо char*. Управляемая версия COM-интерфейса вызывает пользовательскую вызываемую оболочку времени выполнения (Custom Runtime Callable Wrapper, CRCW).

Написание оболочек CRCW не требует сборки взаимодействия, но требует файлы заголовка, которые определяют COM-интерфейсы. Для COM-компонентов, которые включают библиотеки типов, эти заголовки могут быть созданы с помощью MIDL Compiler.

Первая часть следующего кода в примере определяет пользовательскую программу-оболочку, содержащую элементы, которые будут предоставлены управляемому приложению. Вторая часть является консольным приложением, которое использует пользовательскую программу-оболочку для воспроизведения AVI-файлов.

Выполните результирующий EXE-файл с именем допустимого AVI-файла и последний будет воспроизведен в окне.

// 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();
}

См. также

Ссылки

Использование собственных серверов COM в .NET