将对象数组从 C# 返回到 COM 中的 C
Posted
技术标签:
【中文标题】将对象数组从 C# 返回到 COM 中的 C【英文标题】:return array of object from C# to C in COM 【发布时间】:2013-04-30 06:56:03 【问题描述】:我正在使用 COM 在 C++ 和 C# 之间进行通信。
我在 C# 中有以下类
电子邮件地址
/// <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;
邮箱
/// <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;
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;
如何访问从 C# 中的函数返回的 EmailEnity 对象数组(在 C++ 中) 并阅读 EmailEntity 类的字段。请注意,EmailEntity 类包含像这样的成员 EmailAddress[] 本身是一个对象数组。 我计划实现接口 IEmailEntity,其中包含访问 EmailEntity 字段的属性 并使用它来访问 C++ 中的字段。这样做对吗?
如何在 C++ 中访问复杂的字段成员,例如 EmailAddress (EmailAddress[] ToRecipients) 的数组。
请提出建议。
谢谢
【问题讨论】:
【参考方案1】:您可以像这样简化 .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();
【讨论】:
您需要使用 [InterfaceType] 属性才能使此代码正常工作。目前,接口只能通过后期绑定访问,默认为 ComInterfaceType.InterfaceIsIDispatch。 @HansPassant - 此代码可以正常工作。我相信默认是双重的。 你说得对,把我染成紫色。看起来我必须在这里和那里编辑一些答案:( 调试断言失败。 atlsafe.h 中的表达式 psaSrc!=0 。是否因为正在返回 null entity->BccRecepients 这可能会发生,具体取决于您实际返回的内容。我的示例代码在 BccRecipients 中放置了一个数组,所以我不会得到 NULL。以上是关于将对象数组从 C# 返回到 COM 中的 C的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 AJAX (jquery) 将嵌套的对象数组传递和接收到 c# WebMethod 中?