How to return a collection of strings from C# to C++ via COM interop
c#, c++, com, visual-c++
Solution
This just isn't going to work, even if you fix the typos. COM interop doesn't have a standard mapping from `List<T>` to something in COM, and it certainly won't map it to `std::list`. Generics aren't allowed to appear in COM interfaces.
UPDATE
I tried using `ArrayList` as the return type, as that's non-generic I thought maybe the `tlb` would include type information for it. That didn't work so I tried `IList`. That didn't work either (the `#import` statement produced a `.tlh` file that referred to `IList` but had not definition for it.)
So as a workaround I tried declaring a simple list interface. The code ends up like this:
[Guid("7366fe1c-d84f-4241-b27d-8b1b6072af92")]
public interface IStringCollection
{
int Count { get; }
string Get(int index);
}
[Guid("8e8df55f-a90c-4a07-bee5-575104105e1d")]
public interface IMyThing
{
IStringCollection GetListOfStrings();
}
public class StringCollection : List<string>, IStringCollection
{
public string Get(int index)
{
return this[index];
}
}
public class Class1 : IMyThing
{
public IStringCollection GetListOfStrings()
{
return new StringCollection { "Hello", "World" };
}
}
So I have my own (very simplistic) string collection interface. Note that my `StringCollection` class doesn't have to define the `Count` property because it inherits a perfectly good on from `List<string>`.
Then I have this on the C++ side:
#include "stdafx.h"
#import "..\ClassLibrary5.tlb"
#include <vector>
#include <string>
using namespace ClassLibrary5;
int _tmain(int argc, _TCHAR* argv[])
{
CoInitialize(0);
IMyThingPtr thing(__uuidof(Class1));
std::vector<std::string> vectorOfStrings;
IStringCollectionPtr strings(thing->GetListOfStrings());
for (int n = 0; n < strings->GetCount(); n++)
{
const char *pStr = strings->Get(n);
vectorOfStrings.push_back(pStr);
}
return 0;
}
I have to manually copy the contents of the string collection a proper C++ standard container, but it works.
There may be a way to get proper type info from the standard collection classes, so you don't have to make your own collection interfaces, but if not, this should serve okay.
Alternatively, have you looked at C++/CLI? That would work pretty seamlessly, although it still wouldn't convert CLR collections to std containers automatically.
Problem
I hav created a com componet for some Display method in C# it returns a String List as shown below. In v++ i hav used std::lst to catch the return value from Disp() but it gives compiler error that Disp is not a member of class. I i make return type a s void then it works fine. what i can modify so that Disp return a List and in main(c++) i have to use this return value. ``` Public interface ITest { List<string> Disp(); } class TestLib:ITest { List<string> Disp() { List<string> li=new List<string>(); li.Add("stack"); li.Add("over"); li.Add("Flow"); return li; } } ``` compiled and created Test.dll successfully and also test.tlb. Now in main function that is written in c++ ``` #include<list> #import "..\test.tlb" using namespace Test; void main() { HRESULT hr=CoInitialize(null); ITestPtr Ip(__uuidof(TestLib)); std::list<string> li=new std::list<string>(); li=Ip->Disp(); } ``` What's wrong in my code when i try to compile this it shows 'Disp':is not a member of TestLib:ITest how to solve this plz help me ....when i make it return type as void in Class it works fine .what mistake i did????