Procedura: Esporre un contenitore di STL/CLR da un assembly
I contenitori STL/CLR come list e map vengono implementati come classi di riferimento del modello.Poiché i modelli C++ viene creata un'istanza in fase di compilazione, due classi modello che hanno esattamente la stessa firma ma sono in assembly diversi sono effettivamente tipi diversi.Ciò significa che le classi modello non possono essere utilizzate nei limiti dell'assembly.
Per consentire la condivisione dell'croce-assembly, utilizzare i contenitori STL/CLR l'interfaccia generica ICollection<T>.Tramite questa interfaccia generica, tutti i linguaggi che supportano i generics, inclusi C++, c# e Visual Basic, possono accedere ai contenitori STL/CLR.
In questo argomento viene illustrato come visualizzare gli elementi di diversi contenitori STL/CLR scritto in C++ StlClrClassLibrarydenominato assembly.Verranno mostrati due assembly per accedere a StlClrClassLibrary.Il primo assembly viene scritto in C++ e nel secondo in c#.
Se gli assembly vengono scritti in C++, è possibile accedere all'interfaccia generica di un contenitore utilizzando il relativo typedef di generic_container .Ad esempio, se si dispone di un contenitore di tipo cliext::vector<int>, la relativa interfaccia generica è: cliext::vector<int>::generic_container.Analogamente, è possibile ottenere un iteratore su nell'interfaccia generica utilizzando il typedef di generic_iterator , come indicato di seguito: cliext::vector<int>::generic_iterator.
Poiché questi typedef sono dichiarati in un file di intestazione C++, gli assembly scritti in altri linguaggi non possano utilizzarli.Di conseguenza, accedere all'interfaccia generica per cliext::vector<int> in c# o qualsiasi altro linguaggio.NET, utilizzare System.Collections.Generic.ICollection<int>.Per scorrere la raccolta, utilizzare un ciclo di foreach .
Nella tabella seguente sono elencati l'interfaccia generica che ogni contenitore STL/CLR implementa:
Contenitore STL/CLR |
Interfaccia generica |
---|---|
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> |
elenco<t> |
ICollection<t> |
mapping<K, V> |
IDictionary<K, V> |
multimap<K, V> |
IDictionary<K, V> |
multi-insieme<t> |
ICollection<t> |
impostare<t> |
ICollection<t> |
vettore<t> |
ICollection<t> |
[!NOTA]
Poiché queue, priority_queuee i contenitori di stack non supportano gli iteratori, non implementano le interfacce generiche e non possono essere croce-assembly accesso.
Esempio 1
Descrizione
In questo esempio, dichiariamo la classe C++ che contiene i dati dei membri privati STL/CLR.Quindi dichiariamo i metodi pubblici per concedere l'accesso alle raccolte di classe private.La facciamo in due modi diversi, uno per i client C++ e uno per altri client.NET.
Codice
// 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;
};
}
Esempio 2
Descrizione
In questo esempio, implementiamo la classe dichiarata nell'esempio 1.In modo che i client di utilizzare questa libreria di classi, è possibile utilizzare lo strumento manifesto mt.exe per importare il file manifesto nella DLL.Per informazioni dettagliate, vedere i commenti del codice.
Per ulteriori informazioni sullo strumento manifesto e sugli assembly side-by-side, vedere Compilazione di applicazioni isolate C/C++ e di assembly side-by-side.
Codice
// 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;
}
}
Esempio 3
Descrizione
In questo esempio, viene creato il client C++ che utilizza la libreria di classi creata nell'Esempio 1 e a 2.Questo client utilizzano i typedef di generic_container di contenitori STL/CLR per scorrere i contenitori e visualizzare i relativi contenuti.
Codice
// 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;
}
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
Esempio 4
Descrizione
In questo esempio, viene creato un client c# che utilizza la libreria di classi creata nell'Esempio 1 e a 2.Questo client utilizzano i metodi di ICollection<T> di contenitori STL/CLR per scorrere i contenitori e visualizzare i relativi contenuti.
Codice
// 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