views:

1012

answers:

3

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????

A: 

Guess: Disp() is not declared public

n8wrl
+1  A: 

There look like there are several typos. In the C# you declare a class called TestLib, but are trying to construct a TestCls. In addition, neither the class not the method are public (which should be a compile error at least on Disp, since the interface has to be implemented publicly).

plinth
+2  A: 

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.

Daniel Earwicker
Not understand clearly earwicker can u expalin elabarately
Cute