Cómo: Utilizar Servidores COM nativos con CRCWs

Actualización: noviembre 2007

Al contrario que otros lenguajes de .NET, Visual C++ proporciona características de interoperabilidad que permiten el acceso directo y sencillo a API no administradas, incluidas las interfaces COM. Para la interoperabilidad COM en concreto, esto supone importantes ventajas.

Ejemplo

Como el ejemplo de Cómo: Utilizar Servidores COM nativos con TLBIMP, este ejemplo utiliza las interfaces COM definidas en Quartz.dll (que se encuentran en el directorio C:\window\System32) para reproducir archivos AVI. En este caso, sin embargo, se utiliza la interoperabilidad de C++ en lugar de un ensamblado de interoperabilidad independiente generado con Tlbimp.exe. Esta técnica tiene varias ventajas. En este caso, el código de interoperabilidad se integra en la aplicación, por lo que no hay ninguna dependencia en ensamblados aparte. Además, la interfaz administrada expuesta se personaliza para ser más de tipo .NET. Por ejemplo, el método RenderFile toma System.String en lugar de char*. La versión administrada de la interfaz COM es un contenedor personalizado al que se puede llamar en tiempo de ejecución, y se denomina CRCW.

La escritura de CRCW no requiere un ensamblado de interoperabilidad, sino que requiere archivos de encabezado que definan las interfaces COM. Para componentes COM que incluyan bibliotecas de tipos, estos encabezados se pueden generar utilizando el MIDL Compiler.

La primera parte del ejemplo de código siguiente define el contenedor personalizado, que expone los miembros que se expondrán a la aplicación administrada. La segunda parte es una aplicación de consola que utiliza el contenedor personalizado para reproducir archivos AVI.

Ejecute el archivo .exe resultante con el nombre de un archivo AVI válido; el archivo se representa en una ventana.

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

Vea también

Referencia

Utilizar servidores COM nativos de .NET