return array of object from C# to C in COM
See the question and my original answer on StackOverflowYou could simplify the .NET Code like this (remove all MarshalAs that should be done automatically):
[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...
}
To use it with C++, you need to register the DLL and build a .TLB (Type Library file) as explained in a similar answer here: Implement a C# DLL COM File In Unmanaged C++ Program
Then, you can access these classes in C++, like this:
#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();
}