【问题标题】:.NET implementation of C++ interface, exposing to COMC++ 接口的 .NET 实现,向 COM 公开
【发布时间】:2011-11-09 10:37:31
【问题描述】:

我确信我的问题的答案是这个论坛上已经存在的许多主题的组合。也许你可以帮我把这些拼凑起来。

所以我的挑战是,我有一些 C++ 代码实现了如下所示的接口:

interface ItsSupplier : IDispatch {
    [propget, id(1), helpstring("property name") HRESULT Name([out, retval] BSTR* pVal);
}

实现此接口的 DLL 是第三方软件中可用的插件。 我想制作一个用.NET 编写的插件。 由于使用插件的软件不是 .NET,我假设 DLL 必须是 COM 对象。

这是我在 .NET 中的处理方式。

[Guid("xxxx")]
public interface ItsSupplier {
    [DispId(1)]
    [return: MarshalAs(UnmanagedType.Bstr)]
    string Name { get; }
}

[Guid("xxxx"),
ClassInterface(ClassInterfaceType.AutoDispatch),
ComSourceInterfaces(typeof(ItsSupplier))]
    public class SupplierClass : ItsSupplier
    {
        public string { get { return "someName"; } }
    }
}

在项目设置下,我检查了“注册 COM 互操作”。

构建后我运行“regasm testDll.dll”

我的问题是……

自己定义 ItsSupplier 接口是否正确?我的意思是,这是第三方软件所期望的接口,所以必须在其他地方引用它吗?

关于 COM 互操作部分,我做得对吗?

我希望我的解释是正确的:)

干杯 /托马斯

---------------- 汉斯回复后编辑 ------------------------

当我构建 tlb 文件并在 Oleview 中查看原始文件和我的版本时,这就是我得到的。

这是 Oleview 中原始界面插件的样子:

[
  odl,
  uuid(370B4079-40BB-47C9-B797-33B3B5422685),
  helpstring("ItsSupplier Interface"),
  dual,
  oleautomation
]
interface ItsSupplier : IDispatch {

这是我的样子:

[
  odl,
  uuid(370B4079-40BB-47C9-B797-33B3B5422685),
  version(1.0),
  dual,
  oleautomation,
  custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "COMDLL.ItsSupplier")    

]
interface COMDLL_ItsSupplier : IDispatch {

“COMDLL”是我的 Visual Studio 项目的名称。你认为这重要吗?

/托马斯

【问题讨论】:

    标签: .net c++ com


    【解决方案1】:

    不,很多微妙的错误会给你带来麻烦。首先,c++ 接口声明了一个双重接口,通过 IDispatch 支持早期绑定和后期绑定。您必须使用 .NET 中的 [InterfaceType] 属性才能获得相同的效果:

    [ComVisible(true)]
    [Guid("xxxx")]
    [InterfaceType(ComInterfaceType.InterfaceIsDual)]
    public interface ItsSupplier {
        [DispId(1)]
        string Name { get; }
    }
    

    一定要使用 exact 相同的 guid,它在您的 sn-p 中不可见。 [MarshalAs] 属性是不必要的,字符串已经编组为 BSTR。

    接下来是课程。您确实想要公开类实现。这迫使客户端代码也要注意 System.Object,它是所有 .NET 类的基类。它将出现在类型库中。使用 [ComSourceInterfaces] 是不正确的,它应该只应用于事件的调度接口。

    [ComVisible(true)]
    [Guid("xxxx")]
    [ClassInterface(ClassInterfaceType.None)]
    public class SupplierClass : ItsSupplier
    {
        public string Name {
            get { return "someName"; }
        }
    }
    

    再次使用 exact 与 IDL 文件中使用的相同的 guid。接下来是注册。使用“Register for COM interop”选项很好,但是not 再次运行 Regasm.exe。你会搞砸注册。如果您更喜欢手动注册,请始终使用 /codebase 选项,这样程序集就不必安装在 GAC 中。

    最终检查是否一切正确是使用 Tlbexp.exe 创建类型库并使用 Oleview.exe、File + View Typelib 查看它。它应该与您的 IDL 完全匹配。

    【讨论】:

    • 嘿汉斯 非常感谢您的意见,这确实澄清了一些事情。至于在 Oleview 中查看 Tlb 文件,那真是太棒了!请看一下我的回答,了解这让我明白了什么。
    • 没关系,只是tlbexp.exe添加了一些额外的属性。你无法获得 [helpstring]。
    • 这不是在 SO 提问的正确方式。开始一个新问题。
    猜你喜欢
    • 1970-01-01
    • 2017-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-29
    • 2010-09-09
    • 2010-12-31
    相关资源
    最近更新 更多