C#COM可见.Net程序集,其结构来自旧版C++;COM动态链接库 我们有一个C++的COM DLL,它定义了IDL中的一个结构。 IDL的简化版本包含: typedef struct { int num; } LegacyStruct; interface ILegacyInterface : IUnknown { HRESULT GetStruct( [in,out] LegacyStruct* pVal ); }

C#COM可见.Net程序集,其结构来自旧版C++;COM动态链接库 我们有一个C++的COM DLL,它定义了IDL中的一个结构。 IDL的简化版本包含: typedef struct { int num; } LegacyStruct; interface ILegacyInterface : IUnknown { HRESULT GetStruct( [in,out] LegacyStruct* pVal ); },.net,com,interop,com-interop,.net,Com,Interop,Com Interop,现在,我们需要定义一个.NETC#COM可见程序集来实现ILegacyInterface 在C#项目中,我们添加对遗留COM DLL的引用,并定义一个实现此接口的类: [ComVisible( true )] public class CSClass : ILegacyInterface { public void GetStruct( ref LegacyStruct pVal ) { .... } } 目标是在C++COM客户端程序中使用这个COM暴

现在,我们需要定义一个.NETC#COM可见程序集来实现ILegacyInterface

在C#项目中,我们添加对遗留COM DLL的引用,并定义一个实现此接口的类:

[ComVisible( true )]
public class CSClass : ILegacyInterface
{
    public void GetStruct( ref LegacyStruct pVal )
    {
        ....
    }
}
目标是在C++COM客户端程序中使用这个COM暴露的C++汇编类。这个程序应该能够同时使用传统的COM DLL和实现ILegacyInterface的新C#汇编类

编译时,将显示以下警告:
类型库导出器警告处理“CSClass.GetStruct(pVal)”。警告:非COM可见值类型“LegacyStruct”正在从当前导出的类型或其某个基类型引用

由于LegacyStruct不可见,因此生成的程序集的.tlb没有公开GetStruct()方法(即,使用oleview查看时)。
显然,C++ COM客户机没有编译: 错误C2039:“GetStruct”:不是“CSClass”的成员


有没有一种方法确保在C++ C++COM DLL中定义的LeaCySyt在C?com可见的.NET程序集方法中使用时被正确地暴露出来?p> 我意识到这并不能严格回答您关于为什么会发生这种情况的问题,但我在tlbimp中遇到了类似的问题,我学会了如何避免它

我通常发现.Net项目自动导入TLB的方式限制太多。解决这一问题的一种方法是使用所有适当的ComInterface、Guid和CoClass属性在C文件中重新声明IDL内容


tlbimp+reflector也是为这些声明生成框架的好方法。如果您查看tlbimp的反编译结果,您可以看到.Net声明中缺少哪些属性,这可能有助于您了解发生了什么。

我意识到这并不能严格回答您关于为什么会发生这种情况的问题,但我在tlbimp中遇到了类似的问题,我学会了如何避免它

我通常发现.Net项目自动导入TLB的方式限制太多。解决这一问题的一种方法是使用所有适当的ComInterface、Guid和CoClass属性在C文件中重新声明IDL内容


tlbimp+reflector也是为这些声明生成框架的好方法。如果查看tlbimp所做操作的反编译结果,您可以看到.Net声明中缺少哪些属性,这可能有助于您了解发生了什么。

要解决此问题,需要以下两项:

  • 旧式COM IDL必须包含所定义结构的uuid。这是tcarvin在上面提到的。除了uuid之外,结构标记名称必须与结构名称相同。保留标签是不够的,即,即使uuid存在。以下是新的结构定义:

    类型定义[uuid(XXX-YYY-ZZZ-AAA-BBB)]
    结构LegacyStruct
    {
    int num;
    }legacystuct

    没有与结构关联的uuid将在生成的.Net程序集中包含其定义的副本和自动生成的uuid。这显然将是一个完全不同的结构,因为COM涉及相同的名称

  • 当遗留COM DLL被添加为对C#项目的引用时,将“嵌入互操作类型”属性设置为False非常重要。这还将确保遗留COM DLL的定义(例如结构等)不包含在生成的.Net程序集中


  • 要解决此问题,需要以下两项:

  • 旧式COM IDL必须包含所定义结构的uuid。这是tcarvin在上面提到的。除了uuid之外,结构标记名称必须与结构名称相同。保留标签是不够的,即,即使uuid存在。以下是新的结构定义:

    类型定义[uuid(XXX-YYY-ZZZ-AAA-BBB)]
    结构LegacyStruct
    {
    int num;
    }legacystuct

    没有与结构关联的uuid将在生成的.Net程序集中包含其定义的副本和自动生成的uuid。这显然将是一个完全不同的结构,因为COM涉及相同的名称

  • 当遗留COM DLL被添加为对C#项目的引用时,将“嵌入互操作类型”属性设置为False非常重要。这还将确保遗留COM DLL的定义(例如结构等)不包含在生成的.Net程序集中


  • 你真的应该使用C++/CLI包装类与COM通信。你能发布该结构的非简化IDL吗?该结构的非简化版本也很简单。。。typedef结构{long days;long msec;long zone;}LegacyStruct;该结构没有与之关联的uuid,但我尝试了使用uuid和不使用uuid。不幸的是,结果是一样的……请发布LegacyStruct的C#声明。你真的应该使用C++/CLI包装类与COM通信。你能发布该结构的非简化IDL吗?该结构的非简化版本也非常简单。。。typedef结构{long days;long msec;long zone;}LegacyStruct;该结构没有与之关联的uuid,但我尝试了使用uuid和不使用uuid。不幸的是,结果是一样的……请发布LegacyStruct的C#声明