Gewusst wie: Einen STL/CLR-Container einer Assembly verfügbar machen

STL/CLR-Container wie list z. B. und map werden als Vorlagenüberweisungsklassen implementiert. Da C++-Vorlagen zur Kompilierung instanziiert werden, sind zwei Vorlagenklassen, die genau dieselbe Signatur aufweisen, aber in verschiedenen Assemblys vorhanden sind, tatsächlich unterschiedliche Typen. Dies bedeutet, dass Vorlagenklassen nicht über Assemblygrenzen hinweg verwendet werden können.

Um die assemblyübergreifende Freigabe möglich zu machen, implementieren STL/CLR-Container die generische Schnittstelle ICollection<T>. Mithilfe dieser generischen Schnittstelle können alle Sprachen, die Generisches unterstützen, einschließlich C++, C# und Visual Basic, auf STL/CLR-Container zugreifen.

In diesem Thema erfahren Sie, wie Sie die Elemente mehrerer STL/CLR-Container anzeigen, die in einer C++-Assembly mit dem Namen StlClrClassLibrarygeschrieben wurden. Wir zeigen zwei Assemblys für den Zugriff an StlClrClassLibrary. Die erste Assembly wird in C++ und der zweite in C# geschrieben.

Wenn beide Assemblys in C++ geschrieben sind, können Sie mithilfe generic_container der Typedef auf die generische Schnittstelle eines Containers zugreifen. Wenn Sie z. B. über einen Container vom Typ cliext::vector<int>verfügen, lautet die generische Schnittstelle: cliext::vector<int>::generic_container. Ebenso können Sie einen Iterator über die generische Schnittstelle abrufen, indem Sie die generic_iterator Typedef wie in: verwenden. cliext::vector<int>::generic_iterator

Da diese Typedefs in C++-Headerdateien deklariert werden, können Assemblys, die in anderen Sprachen geschrieben wurden, nicht verwenden. Verwenden Sie System.Collections.Generic.ICollection<int>daher, um auf die generische Schnittstelle für cliext::vector<int> C# oder eine andere .NET-Sprache zuzugreifen. Verwenden Sie eine foreach Schleife, um diese Auflistung zu durchlaufen.

In der folgenden Tabelle sind die generische Schnittstelle aufgeführt, die von jedem STL/CLR-Container implementiert wird:

STL/CLR-Container Generische Schnittstelle
deque<T> ICollection<T>
hash_map<K, V> IDictionary<K, V>
hash_multimap<K, V> IDictionary<K, V>
hash_multiset<T> ICollection<T>
hash_set<T> ICollection<T>
list<T> ICollection<T>
map<K, V> IDictionary<K, V>
multimap<K, V> IDictionary<K, V>
multiset<T> ICollection<T>
set<T> ICollection<T>
vector<T> ICollection<T>

Hinweis

Da die queueIteratoren priority_queueund stack Container keine iteratoren unterstützen, implementieren sie keine generischen Schnittstellen und können nicht auf assemblyübergreifende Assemblys zugegriffen werden.

Beispiel 1

Beschreibung

In diesem Beispiel deklarieren wir eine C++-Klasse, die private STL/CLR-Memberdaten enthält. Anschließend deklarieren wir öffentliche Methoden, um den Zugriff auf die privaten Sammlungen der Klasse zu gewähren. Wir tun dies auf zwei verschiedene Arten, eine für C++-Clients und eine für andere .NET-Clients.

Code

// StlClrClassLibrary.h
#pragma once

#include <cliext/deque>
#include <cliext/list>
#include <cliext/map>
#include <cliext/set>
#include <cliext/stack>
#include <cliext/vector>

using namespace System;
using namespace System::Collections::Generic;
using namespace cliext;

namespace StlClrClassLibrary {

    public ref class StlClrClass
    {
    public:
        StlClrClass();

        // These methods can be called by a C++ class
        // in another assembly to get access to the
        // private STL/CLR types defined below.
        deque<wchar_t>::generic_container ^GetDequeCpp();
        list<float>::generic_container ^GetListCpp();
        map<int, String ^>::generic_container ^GetMapCpp();
        set<double>::generic_container ^GetSetCpp();
        vector<int>::generic_container ^GetVectorCpp();

        // These methods can be called by a non-C++ class
        // in another assembly to get access to the
        // private STL/CLR types defined below.
        ICollection<wchar_t> ^GetDequeCs();
        ICollection<float> ^GetListCs();
        IDictionary<int, String ^> ^GetMapCs();
        ICollection<double> ^GetSetCs();
        ICollection<int> ^GetVectorCs();

    private:
        deque<wchar_t> ^aDeque;
        list<float> ^aList;
        map<int, String ^> ^aMap;
        set<double> ^aSet;
        vector<int> ^aVector;
    };
}

Beispiel 2

Beschreibung

In diesem Beispiel implementieren wir die in Beispiel 1 deklarierte Klasse. Damit Clients diese Klassenbibliothek verwenden können, verwenden wir das Manifesttool mt.exe , um die Manifestdatei in die DLL einzubetten. Ausführliche Informationen finden Sie in den Codekommentaren.

Weitere Informationen zum Manifesttool und parallelen Assemblys finden Sie unter Building C/C++ Isolated Applications and Side-by-Side Assemblies.

Code

// StlClrClassLibrary.cpp
// compile with: /clr /LD /link /manifest
// post-build command: (attrib -r StlClrClassLibrary.dll & mt /manifest StlClrClassLibrary.dll.manifest /outputresource:StlClrClassLibrary.dll;#2 & attrib +r StlClrClassLibrary.dll)

#include "StlClrClassLibrary.h"

namespace StlClrClassLibrary
{
    StlClrClass::StlClrClass()
    {
        aDeque = gcnew deque<wchar_t>();
        aDeque->push_back(L'a');
        aDeque->push_back(L'b');

        aList = gcnew list<float>();
        aList->push_back(3.14159f);
        aList->push_back(2.71828f);

        aMap = gcnew map<int, String ^>();
        aMap[0] = "Hello";
        aMap[1] = "World";

        aSet = gcnew set<double>();
        aSet->insert(3.14159);
        aSet->insert(2.71828);

        aVector = gcnew vector<int>();
        aVector->push_back(10);
        aVector->push_back(20);
    }

    deque<wchar_t>::generic_container ^StlClrClass::GetDequeCpp()
    {
        return aDeque;
    }

    list<float>::generic_container ^StlClrClass::GetListCpp()
    {
        return aList;
    }

    map<int, String ^>::generic_container ^StlClrClass::GetMapCpp()
    {
        return aMap;
    }

    set<double>::generic_container ^StlClrClass::GetSetCpp()
    {
        return aSet;
    }

    vector<int>::generic_container ^StlClrClass::GetVectorCpp()
    {
        return aVector;
    }

    ICollection<wchar_t> ^StlClrClass::GetDequeCs()
    {
        return aDeque;
    }

    ICollection<float> ^StlClrClass::GetListCs()
    {
        return aList;
    }

    IDictionary<int, String ^> ^StlClrClass::GetMapCs()
    {
        return aMap;
    }

    ICollection<double> ^StlClrClass::GetSetCs()
    {
        return aSet;
    }

    ICollection<int> ^StlClrClass::GetVectorCs()
    {
        return aVector;
    }
}

Beispiel 3

Beschreibung

In diesem Beispiel erstellen wir einen C++-Client, der die klassenbibliothek verwendet, die in Den Beispielen 1 und 2 erstellt wurde. Dieser Client verwendet die generic_container Typedefs der STL/CLR-Container, um die Container zu durchlaufen und deren Inhalt anzuzeigen.

Code

// CppConsoleApp.cpp
// compile with: /clr /FUStlClrClassLibrary.dll

#include <cliext/deque>
#include <cliext/list>
#include <cliext/map>
#include <cliext/set>
#include <cliext/vector>

using namespace System;
using namespace StlClrClassLibrary;
using namespace cliext;

int main(array<System::String ^> ^args)
{
    StlClrClass theClass;

    Console::WriteLine("cliext::deque contents:");
    deque<wchar_t>::generic_container ^aDeque = theClass.GetDequeCpp();
    for each (wchar_t wc in aDeque)
    {
        Console::WriteLine(wc);
    }
    Console::WriteLine();

    Console::WriteLine("cliext::list contents:");
    list<float>::generic_container ^aList = theClass.GetListCpp();
    for each (float f in aList)
    {
        Console::WriteLine(f);
    }
    Console::WriteLine();

    Console::WriteLine("cliext::map contents:");
    map<int, String ^>::generic_container ^aMap = theClass.GetMapCpp();
    for each (map<int, String ^>::value_type rp in aMap)
    {
        Console::WriteLine("{0} {1}", rp->first, rp->second);
    }
    Console::WriteLine();

    Console::WriteLine("cliext::set contents:");
    set<double>::generic_container ^aSet = theClass.GetSetCpp();
    for each (double d in aSet)
    {
        Console::WriteLine(d);
    }
    Console::WriteLine();

    Console::WriteLine("cliext::vector contents:");
    vector<int>::generic_container ^aVector = theClass.GetVectorCpp();
    for each (int i in aVector)
    {
        Console::WriteLine(i);
    }
    Console::WriteLine();

    return 0;
}

Ausgabe

cliext::deque contents:
a
b

cliext::list contents:
3.14159
2.71828

cliext::map contents:
0 Hello
1 World

cliext::set contents:
2.71828
3.14159

cliext::vector contents:
10
20

Beispiel 4

Beschreibung

In diesem Beispiel erstellen wir einen C#-Client, der die klassenbibliothek verwendet, die in Den Beispielen 1 und 2 erstellt wurde. Dieser Client verwendet die ICollection<T> Methoden der STL/CLR-Container, um die Container zu durchlaufen und deren Inhalt anzuzeigen.

Code

// CsConsoleApp.cs
// compile with: /r:Microsoft.VisualC.STLCLR.dll /r:StlClrClassLibrary.dll /r:System.dll

using System;
using System.Collections.Generic;
using StlClrClassLibrary;
using cliext;

namespace CsConsoleApp
{
    class Program
    {
        static int Main(string[] args)
        {
            StlClrClass theClass = new StlClrClass();

            Console.WriteLine("cliext::deque contents:");
            ICollection<char> iCollChar = theClass.GetDequeCs();
            foreach (char c in iCollChar)
            {
                Console.WriteLine(c);
            }
            Console.WriteLine();

            Console.WriteLine("cliext::list contents:");
            ICollection<float> iCollFloat = theClass.GetListCs();
            foreach (float f in iCollFloat)
            {
                Console.WriteLine(f);
            }
            Console.WriteLine();

            Console.WriteLine("cliext::map contents:");
            IDictionary<int, string> iDict = theClass.GetMapCs();
            foreach (KeyValuePair<int, string> kvp in iDict)
            {
                Console.WriteLine("{0} {1}", kvp.Key, kvp.Value);
            }
            Console.WriteLine();

            Console.WriteLine("cliext::set contents:");
            ICollection<double> iCollDouble = theClass.GetSetCs();
            foreach (double d in iCollDouble)
            {
                Console.WriteLine(d);
            }
            Console.WriteLine();

            Console.WriteLine("cliext::vector contents:");
            ICollection<int> iCollInt = theClass.GetVectorCs();
            foreach (int i in iCollInt)
            {
                Console.WriteLine(i);
            }
            Console.WriteLine();

            return 0;
        }
    }
}

Output

cliext::deque contents:
a
b

cliext::list contents:
3.14159
2.71828

cliext::map contents:
0 Hello
1 World

cliext::set contents:
2.71828
3.14159

cliext::vector contents:
10
20

Siehe auch

Referenz zur STL/CLR-Bibliothek