如何在idl中声明一个IStream,以便visual studio将其映射到s.w.interop.comtypes?

时间:2010-04-22 13:17:54

标签: c# interop idl istream midl

我有一个COM对象需要从C#客户端获取流并对其进行处理。看来我应该使用IStream。所以我写下我的idl。然后我使用MIDL编译为tlb,编译我的解决方案,注册它,然后将我的库的引用添加到C#项目。

Visual Studio在我自己的库中创建一个IStream定义。如何阻止它这样做,让它使用COMTypes IStream?似乎有3个答案之一: 添加一些导入

  • 到idl所以它不会重新声明IStream(导入MSCOREE会这样做,但不解决C#问题)
  • 以某种方式将视觉工作室中的IStream别名 - 但我不知道如何做到这一点。
  • 我的所有想法都完全错了,我不应该一直使用IStream

帮助...谢谢

[
  uuid(3AC11584-7F6A-493A-9C90-588560DF8769),
  version(1.0),
]
library TestLibrary
{

  importlib("stdole2.tlb");

  [
    uuid(09FF25EC-6A21-423B-A5FD-BCB691F93C0C),
    version(1.0),
    helpstring("Just for testing"),
    dual,
    nonextensible,
    oleautomation
  ]
  interface ITest: IDispatch
  {
    [id(0x00000006),helpstring("Testing stream")]
    HRESULT _stdcall LoadFromStream([in] IStream * stream, [out, retval] IMyTest ** ResultValue);
  };

  [
    uuid(CC2864E4-55BA-4057-8687-29153BE3E046),
    noncreatable,
    version(1.0)
  ]
  coclass HCTest
  {
     [default] interface ITest;
  };

};

2 个答案:

答案 0 :(得分:1)

您所看到和体验的是MIDL编译器的一个功能(通常很烦人)。在"库中引用的任何类型" section将其定义注入tlb(类型库);除了IUnknown接口和MIDL base types之外,(可能还有一些更原始的类型)。你看到的那些奇怪的方法"你的" IStream来自基类型ISequentialStream。您有几个选择:

  1. 与MIDL编译器搏斗了好几天,试图通过注入IStream(及其所有其他支持类型)来获取它。我做到了这一点。它也与Mscoree有关。问题是MIDL编译器会自动导入" oaidl.idl"当它遇到库声明时。因此,在您有机会对其进行任何操作之前,这些类型(Stream等)已经注入到当前的IDL上下文中。这是一个记录不完整的功能。除非你删除对IStream的硬引用(使用PVOID [*]流),否则无论你做什么都会做到底线。

  2. 忽略它。不要使用它。请改用System.Runtime.InteropServices.ComTypes.IStream。只要您使用的接口(在.Net中)标记有正确的属性(Guid,InterfaceType等),它们就是可互换的。您必须编辑类型库或互操作代码,以便它接受您希望传递的类型。我会使用对象,因此您可以使用任何IStream接口(具有有效的定义)。并且也不使用旧的TlbImp工具。使用新的TlbImp2(用C#和开源编写)https://clrinterop.codeplex.com/releases/view/17579。它允许您真正自定义从TLB到Managed的转换,除了编译的interop dll之外,您还可以生成源文件而不是/。

答案 1 :(得分:0)

这不需要修复,从类型库创建的interop包装器就可以了。 ComTypes.IStream声明允许托管代码实现实现IStream的COM服务器或将其作为参数。很多.NET框架类都可以。