2013-04-30 95 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