C ++接口的.NET实现,暴露给COM

时间:2011-11-09 10:37:32

标签: .net c++ com

我确信我的问题的答案是本论坛上已有的许多主题的组合。也许你可以帮我把各个部分放在一起。

所以我的挑战是,我有一些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 interorp”。

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

我的问题是......

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

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

我希望我能解释这一点:)

干杯 /托马斯

---------------- HANS回应后的编辑------------------------

当我构建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项目的名称。你认为这很重要吗?

/托马斯

1 个答案:

答案 0 :(得分:3)

不,很多微妙的错误会让你陷入困境。首先,c ++接口声明了一个双接口,通过IDispatch支持早期绑定和后期绑定。您必须使用.NET中的[InterfaceType]属性来获得相同的内容:

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

请务必使用完全相同的guid,它在您的代码段中不可见。 [MarshalAs]属性是不必要的,字符串已经作为BSTR编组。

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

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

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

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