2013-04-30 93 views
2

我正在使用COM在C++和C#之间进行通信。将C#中的对象数组返回给COM中的C

我在C#中的以下类

  1. 电子邮件地址

    /// <summary> 
    /// Email Address 
    /// </summary> 
    public class EmailAddress 
    { 
        /// <summary> 
        /// SMTP Address 
        /// </summary> 
        [MarshalAs(UnmanagedType.BStr)]   
        public string Address; 
    
        /// <summary> 
        /// Name 
        /// </summary> 
        [MarshalAs(UnmanagedType.BStr)] 
        public string Name; 
    } 
    
  2. 邮箱

    /// <summary> 
    /// MailBox Entity 
    /// </summary> 
    public struct MailBoxEntity 
    { 
        /// <summary> 
        /// SMTP Address 
        /// </summary> 
        [MarshalAs(UnmanagedType.BStr)] 
        public string SMTPAddress; 
    
        /// <summary> 
        /// Mailbox Display Name 
        /// </summary> 
        [MarshalAs(UnmanagedType.BStr)] 
        public string Name; 
    
        /// <summary> 
        /// Mailbox Server Name 
        /// </summary> 
        [MarshalAs(UnmanagedType.BStr)] 
        public string sServerName; 
    } 
    
  3. EmailEntity(尚未落实IEmailEntity将包含每个字段属性)

    /// <summary> 
    /// Class for Email Entity 
    /// </summary> 
    public class EmailEntity : IEmailEntity 
    { 
        /// <summary> 
        /// BccRecipients 
        /// </summary> 
        [MarshalAs(UnmanagedType.ByValArray)] 
        public EmailAddress[] BccRecipients; 
    
        /// <summary> 
        /// Body 
        /// </summary> 
        [MarshalAs(UnmanagedType.BStr)] 
        public string Body; 
    
        /// <summary> 
        /// CcRecipients 
        /// </summary> 
        [MarshalAs(UnmanagedType.ByValArray)] 
        public EmailAddress[] CcRecipients; 
    
        /// <summary> 
        /// Culture 
        /// </summary> 
        [MarshalAs(UnmanagedType.BStr)] 
        public string Culture; 
    
        /// <summary> 
        /// DateTimeCreated 
        /// </summary> 
        [MarshalAs(UnmanagedType.BStr)] 
        public string DateTimeCreated; 
    
        /// <summary> 
        /// DateTimeReceived 
        /// </summary> 
        [MarshalAs(UnmanagedType.BStr)] 
        public string DateTimeReceived; 
    
        /// <summary> 
        /// DateTimeSent 
        /// </summary> 
        [MarshalAs(UnmanagedType.BStr)] 
        public string DateTimeSent; 
    
        /// <summary> 
        /// FromAddress 
        /// </summary> 
        [MarshalAs(UnmanagedType.BStr)] 
        public string FromAddress; 
    
        /// <summary> 
        /// FromName 
        /// </summary> 
        [MarshalAs(UnmanagedType.BStr)] 
        public string FromName; 
    
    
        /// <summary> 
        /// HasAttachments 
        /// </summary> 
        [MarshalAs(UnmanagedType.BStr)] 
        public string HasAttachments; 
    
        /// <summary> 
        /// Id 
        /// </summary> 
        [MarshalAs(UnmanagedType.BStr)] 
        public string Id; 
    
        /// <summary> 
        /// Importance 
        /// </summary> 
        [MarshalAs(UnmanagedType.BStr)] 
        public string Importance; 
    
        /// <summary> 
        /// LastModifiedName 
        /// </summary> 
        [MarshalAs(UnmanagedType.BStr)] 
        public string LastModifiedName; 
    
        /// <summary> 
        /// LastModifiedTime 
        /// </summary> 
        [MarshalAs(UnmanagedType.BStr)] 
        public string LastModifiedTime; 
    
        /// <summary> 
        /// MimeContent 
        /// </summary> 
        [MarshalAs(UnmanagedType.BStr)] 
        public string MimeContent; 
    
        /// <summary> 
        /// ParentFolderId 
        /// </summary> 
        [MarshalAs(UnmanagedType.BStr)] 
        public string ParentFolderId; 
    
        /// <summary> 
        /// Original Mailbox 
        /// </summary> 
        [MarshalAs(UnmanagedType.BStr)] 
        public MailBoxEntity OriginalMailBox; 
    
    
        /// <summary> 
        /// ParentFolderName 
        /// </summary> 
        [MarshalAs(UnmanagedType.BStr)] 
        public string ParentFolderName; 
    
        /// <summary> 
        /// ReceivedByAddress 
        /// </summary> 
        [MarshalAs(UnmanagedType.BStr)] 
        public string ReceivedByAddress; 
    
        /// <summary> 
        /// ReceivedByName 
        /// </summary> 
        [MarshalAs(UnmanagedType.BStr)] 
        public string ReceivedByName; 
    
        /// <summary> 
        /// Size 
        /// </summary> 
        [MarshalAs(UnmanagedType.BStr)] 
        public string Size; 
    
        /// <summary> 
        /// Subject 
        /// </summary> 
        [MarshalAs(UnmanagedType.BStr)] 
        public string Subject; 
    
        /// <summary> 
        /// ToRecipients 
        /// </summary> 
        [MarshalAs(UnmanagedType.ByValArray)] 
        public EmailAddress[] ToRecipients; 
    
    } 
    

如何访问访问阵列EmailEnity的对象(在C++)从C# 函数返回并读取EmailEntity类的字段。请注意,EmailEntity类包含 EmailAddress []这样的成员,它本身就是一个对象数组。 我打算实现包含属性的接口IEmailEntity,以访问EmailEntity 的字段并使用它来访问C++中的字段。这是正确的方式吗?

如何在C++中访问诸如EmailAddress(EmailAddress [] ToRecipients)数组的复杂字段成员。

请建议。

感谢

回答

4

你可以简化.NET这样的代码(删除应自动完成所有的MarshalAs):

[ComVisible(true)] 
public class MyRootClass : IMyRootClass // some class to start with 
{ 
    public IEmailEntity[] GetEntities() 
    { 
     List<IEmailEntity> list = new List<IEmailEntity>(); 
     for(int i = 0; i < 10; i++) 
     { 
      EmailEntity entity = new EmailEntity(); 
      List<IEmailAddress> addresses = new List<IEmailAddress>(); 
      addresses.Add(new EmailAddress { Name = "Joe" + i }); 
      entity.BccRecipients = addresses.ToArray(); 
      entity.Body = "hello world " + i; 
      list.Add(entity); 
     } 
     return list.ToArray(); 
    } 
} 

[ComVisible(true)] 
public interface IMyRootClass 
{ 
    IEmailEntity[] GetEntities(); 
} 

public class EmailEntity : IEmailEntity 
{ 
    public IEmailAddress[] BccRecipients { get; set; } 
    public string Body { get; set; } 
} 

public class EmailAddress : IEmailAddress 
{ 
    public string Address { get; set; } 
    public string Name { get; set; } 
} 

[ComVisible(true)] 
public interface IEmailAddress 
{ 
    string Address { get; set; } 
    string Name { get; set; } 
} 

[ComVisible(true)] 
public interface IEmailEntity 
{ 
    IEmailAddress[] BccRecipients { get; set; } 
    string Body { get; set; } 
    // to be continued... 
} 

用C++使用它,你需要注册的DLL和构建一个.TLB(类型库文件)作为一个类似的答案了说明:Implement a C# DLL COM File In Unmanaged C++ Program

然后,您可以在C访问这些类++,就像这样:

#include "stdafx.h" 
#import "c:\MyPathToTheTlb\YourAssembly.tlb" // import the COM TLB 

using namespace YourAssembly; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    CoInitialize(NULL); 
    IMyRootClassPtr ptr(__uuidof(MyRootClass)); 
    CComSafeArray<IUnknown*> entities = ptr->GetEntities(); // CComSafeArray needs atlsafe.h in the PCH 
    for(int i = entities.GetLowerBound(0); i <= entities.GetUpperBound(0); i++) 
    { 
    IEmailEntityPtr entity; 
    entities.GetAt(i).QueryInterface(&entity); 
    _bstr_t body = entity->Body; 
    printf("%S\n", body.GetBSTR()); 

    CComSafeArray<IUnknown*> recipients = entity->BccRecipients; 
    for(int j = recipients.GetLowerBound(0); j <= recipients.GetUpperBound(0); j++) 
    { 
     IEmailAddressPtr address; 
     recipients.GetAt(j).QueryInterface(&address); 
     _bstr_t name = address->Name; 
     printf(" %S\n", name.GetBSTR()); 
    } 
    } 
    CoUninitialize(); 
} 
+0

您将需要使用[InterfaceType]属性来使此代码有效。现在,接口只能在后期绑定,默认是ComInterfaceType.InterfaceIsIDispatch。 – 2013-04-30 11:10:04

+0

@HansPassant - 此代码正常工作。我相信默认是双重的。 – 2013-04-30 11:41:06

+0

你说得对,给我涂上紫色。看起来我将不得不编辑一些答案在这里和那里:( – 2013-04-30 12:04:50