如何:将本机 COM 服务器与 CRCW 一起使用

更新:2007 年 11 月

与其他 .NET 语言不同,Visual C++ 提供了允许直接并无缝访问非托管 API(包括 COM 接口)的互操作功能。特别是对于 COM Interop 而言,这提供了强大的优势。

示例

如何:将本机 COM 服务器用于 TLBIMP 中的示例相似,此示例使用 Quartz.dll(在 C:\window\System32 目录中)中定义的 COM 接口来播放 AVI 文件。但是在此情况下,将使用 C++ Interop 而不是由 Tlbimp.exe 生成的单独互操作程序集。这项技术有几个优点。在此情况下,将在应用程序中内置互操作代码,所以不依赖于单独程序集。而且,公开的托管接口被自定义为更像 .NET。例如,RenderFile 方法接受 System.String 而不是 char*。COM 接口的托管版本被称为自定义运行库可调用包装 (CRCW)。

编写 CRCW 不需要互操作程序集,但需要定义 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 服务器