Partager via


Comment : Exposez un conteneur STL/CLR d'un assembly

Les conteneurs STL/CLR tels que list et map sont implémentés en tant que modèles de classes de référence. Étant donné que les modèles C++ sont instanciés au moment de la compilation, deux classes de modèle ayant exactement la même signature mais se trouvant dans des assemblys différents sont en fait des types différents. Cela signifie que les classes du modèle ne peuvent pas être utilisées en-dehors des limites de l'assembly.

Pour rendre le partage d'assembly croisé possible, les conteneurs STL/CLR implémentent l'interface générique ICollection. À l'aide de cette interface générique, tous les langages qui prennent en charge les génériques, notamment C++, C# et Visual Basic, peuvent accéder aux conteneurs STL ou CLR.

Cette rubrique vous montre comment afficher les éléments de plusieurs conteneurs STL/CLR écrits dans un assembly C++ nommé StlClrClassLibrary. Nous indiquons deux assemblys pour accéder à StlClrClassLibrary. Le premier assembly est écrit en C++, et le second en C#.

Si les deux assemblys sont écrits en C++, vous pouvez accéder à l'interface générique d'un conteneur à l'aide de son typedef generic_container. Par exemple, si vous avez un conteneur de type cliext::vector<int>, alors son interface générique est : cliext::vector<int>::generic_container. De même, vous pouvez obtenir une itération au sein de l'interface générique à l'aide du typedef generic_iterator, comme dans : cliext::vector<int>::generic_iterator.

Comme ces typedefs sont déclarés dans les fichiers d'en-tête C++, les assemblys écrits dans d'autres langages ne peuvent pas les utiliser. Par conséquent, pour accéder à l'interface générique pour cliext::vector<int> en C# ou en tout autre langage .NET, utilisez System.Collections.Generic.ICollection<int>. Pour effectuer une itération au sein de la collection, utilisez une boucle foreach.

Le tableau suivant répertorie l'interface générique que chaque conteneur STL/CLR implémente :

Conteneur STL/CLR

Interface générique

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>

Notes

Comme les conteneurs queue, priority_queue, stack ne prennent pas en charge les itérateurs, ils n'implémentent pas les interfaces génériques et ne peuvent pas posséder un accès en assembly croisé.

Exemple 1

Description

Dans cet exemple, nous déclarons la classe actuelle c ++ qui contient des données privées membres de STL/CLR. Nous déclarons alors les méthodes publiques pour accorder un accès aux collections privées de la classe. Nous le faisons de deux façons différentes, l'une pour les clients C++ et l'autre pour les autres clients .NET.

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

Exemple 2

Description

Dans cet exemple, nous implémentons la classe déclarée dans l'exemple 1. Pour que les clients utilisent cette bibliothèque de classes, nous utilisons l'outil manifeste mt.exe pour inclure le fichier de manifeste dans la DLL. Pour plus d'informations, consultez les commentaires de code.

Pour plus d'informations sur l'outil et les assemblys côte à côte manifestes, consultez Génération d'applications isolées C/C++ et d'assemblys côte à côte.

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

Exemple 3

Description

Dans cet exemple, nous créons un client C ++ qui utilise la bibliothèque de classes créée dans les exemples 1 et 2. Ce client utilise les typedefs generic_container des conteneurs STL/CLR pour parcourir les conteneurs et afficher leur contenu.

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

Sortie

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

Exemple 4

Description

Dans cet exemple, nous créons un client C# qui utilise la bibliothèque de classes créée dans les exemples 1 et 2. Ce client utilise les méthodes ICollection des conteneurs STL/CLR pour parcourir les conteneurs et afficher leur contenu.

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

Sortie

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

Voir aussi

Autres ressources

Référence de bibliothèque STL/CLR