Как вернуть коллекцию строк из C # в C ++ через COM-взаимодействие - PullRequest
3 голосов
/ 23 июня 2009

Я создал com-компонент для некоторого метода Display в C #, он возвращает список строк

как показано ниже. В v ++ я использовал std :: lst, чтобы поймать возвращаемое значение из Disp (), но оно

выдает ошибку компилятора, что Disp не является членом класса. Если я сделаю тип возврата пустым, то

работает нормально. что я могу изменить, чтобы Disp возвращал список, а в main (c ++) я должен использовать

это возвращаемое значение.

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;
    }
}

успешно скомпилировал и создал Test.dll, а также test.tlb. Теперь в основной функции, которая написана на 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();
}

Что не так в моем коде, когда я пытаюсь скомпилировать это, он показывает

'Disp': не является членом TestLib: ITest

как решить эту проблему, пожалуйста, помогите мне .... когда я возвращаю тип как void в классе, он работает нормально. Какую ошибку я совершил ????

Ответы [ 3 ]

7 голосов
/ 23 июня 2009

Это просто не сработает, даже если вы исправите опечатки. COM-взаимодействие не имеет стандартного сопоставления с List<T> на что-то в COM, и, конечно, оно не будет сопоставлять его с std::list Дженерики не могут появляться в интерфейсах COM.

UPDATE

Я попытался использовать ArrayList в качестве возвращаемого типа, поскольку это не является универсальным, я подумал, что, возможно, tlb будет включать информацию о типе для него. Это не сработало, поэтому я попытался IList. Это тоже не сработало (оператор #import создал файл .tlh, который ссылался на IList, но не имел определения для него.)

Так что в качестве обходного пути я попытался объявить простой интерфейс списка. Код заканчивается так:

[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" };
    }
}

Так что у меня есть собственный (очень упрощенный) интерфейс для сбора строк. Обратите внимание, что мой класс StringCollection не должен определять свойство Count, потому что он наследует отлично от List<string>.

Тогда у меня есть это на стороне C ++:

#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;
}

Мне нужно вручную скопировать содержимое коллекции строк в соответствующий стандартный контейнер C ++, но это работает.

Может быть способ получить правильную информацию о типах из стандартных классов коллекций, так что вам не нужно создавать собственные интерфейсы коллекций, но если нет, это должно сработать.

В качестве альтернативы, вы смотрели на C ++ / CLI? Это будет работать без проблем, хотя все равно не будет автоматически конвертировать коллекции CLR в стандартные контейнеры.

1 голос
/ 23 июня 2009

Похоже, есть несколько опечаток. В C # вы объявляете класс с именем TestLib, но пытаетесь создать TestCls. Кроме того, ни класс, ни метод не являются общедоступными (что должно быть ошибкой компиляции по крайней мере в Disp, поскольку интерфейс должен быть реализован публично).

0 голосов
/ 23 июня 2009

думаю: Disp () не объявлен публичным

...