c# - 使用 COM 在 C++ 中实例化 C# 类成员

标签 c# c++ class com

我想在 C++ 中创建一个 C# 类对象并设置其成员字段。 尽管我能够创建 C++ 类对象,但我无法访问它的成员并设置成员字段值。

/// <summary>
/// Class for AQS Entity
/// </summary>
[ClassInterface(ClassInterfaceType.None)]
[Guid("70F12A44-B91D-474D-BD70-32B1ACE041D6")]
[ProgId("AQSEntity")]
public class AQSEntity : IEntity
{

    public AQSEntity()
    {
        sRecoveryDBName = String.Empty;
        arrSourceMailboxesEntity = null;
        sQueryString = String.Empty;
    }

    [MarshalAs(UnmanagedType.BStr)]
    public string sRecoveryDBName = string.Empty;

    [MarshalAs(UnmanagedType.ByValArray)]
    public MailBoxCollection arrSourceMailboxesEntity;

    [MarshalAs(UnmanagedType.BStr)]
    public string sQueryString;


}

下面定义了 IEntity 类

[Guid("5C71057E-9FD9-47D5-B022-8D5F9C7007D3")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IEntity
{
}

在 C++ 中,

IEntity* pTest1 = NULL;
hr = CoCreateInstance(__uuidof(**AQSEntity**),NULL,CLSCTX_INPROC_SERVER,__uuidof(IEntity),(void**)&pTest1);

我想访问 C++ 中 AQSEntity 类的成员。但我无法访问它们。

pTest1->sQueryString

给出错误。

'sQueryString' : is not a member of 'AsigraExchange::IEntity' C:\PROJECTS\COM\COMClient\COMClient.cpp 168

任何人都可以建议我错在哪里。

谢谢, 加根

最佳答案

一切都按照它应该的方式运行:)

在您的 C++ 项目中,您可以访问在您的 IEntity 接口(interface)上声明的所有方法,但实际上没有。

您的实现,即 AQSEntity 类,应该实现所有 IEntity 成员。现在在该类中声明的方法是该类的成员,它们与 IEntity 没有任何关系。

这意味着您需要在IEntity 接口(interface)中声明所有必需的方法,然后在AQSEntity 中实现它们。请注意,您还公开了类的字段,而不是方法。您将必须定义方法(或属性,将在 C++ 端转换为方法)然后实现它们。像这样的东西:

public interface IEntity
{
    public string RecoveryDBName { get; }
}

您还必须在接口(interface)中指定 [MarshalAs] 属性,尽管 UnmanagedType.BStr 是字符串的默认属性,因此您可以省略它们。

编辑:

根据评论,似乎 IEntity 只是一个标记接口(interface),不打算作为 API 公开(属性可能是这里更好的选择,因为 IEntity 赢了' 无论如何都要在客户端使用)。

在这种情况下有两种选择:

1) 更好的方法,尽管它需要更多的工作:从 IEntity 派生 IAQSEntity 接口(interface),在其上声明方法,并在 AQSEntity 上实现它> 类

2) 工作更少,但更脆弱:将 AQSEntity 标记为 ClassInterfaceType.AutoDual 而不是 ClassInterfaceType.None - 这将公开成员到 COM 客户端,但将更难进行版本控制,并且还会公开基类型成员。

这是我会选择的:

[ClassInterface(ClassInterfaceType.None)]
...
[Entity]  // instead of IEntity marker interface
public class AQSEntity : IAQSEntity
{
    public string RecoveryDbName { get; }
}

[Guid("...")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IAQSEntity // no base interface IEntity!
{
    string RecoveryDbName { get; }        
}

使用 Entity 属性而不是 IEntity 标记接口(interface)的唯一缺点是,如果您想将该接口(interface)用作泛型的约束

关于c# - 使用 COM 在 C++ 中实例化 C# 类成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16274422/

相关文章:

c# - 将 IEnumerable<int> 初始化为可选参数

c++ - (QT) QThread 不执行第二次

Ruby 模块可以访问它所需要的类方法吗?

c# - 奇怪的 DllImport 行为(仅在 Unity3d 中)

c++ - 为什么当我改变它的位置时光源没有移动?

c++ - 在类的最大实例化上引发错误

class - 如何找到调用此方法的 ABAP 程序/FM?

除 Pascal 和全部大写之外的常量的 C# 命名约定

C# 泛型和泛型约束

c# - 如何从 C# 中的 C++ dll 中使用具有全局变量的函数获取返回数组?