Gewusst wie: Einen STL/CLR-Container einer Assembly verfügbar machen
STL/CLR-Container wie list und map werden als Vorlagenverweisklassen implementiert. Da C++-Vorlagen zur Kompilierzeit instanziiert werden, zwei Vorlagenklassen, die genau die gleiche Signatur haben, jedoch, in unterschiedlichen Assemblys sind tatsächlich verschiedene Typen sind. Dies bedeutet, dass Vorlagenklassen nicht über Assemblygrenzen verwendet werden können.
So assemblyübergreifende Freigabe ist, STL/CLR-Containerwerkzeug die generische ICollection- Schnittstelle. Mithilfe dieser generische Schnittstelle verwenden, können alle Sprachen, einschließlich Generika, die C++, C# und Visual Basic unterstützen, auf STL/CLR-Container zugreifen.
Dieses Thema veranschaulicht, wie die Elemente verschiedener STL/CLR-Container anzeigt, die in eine C++-Datei Assembly mit dem Namen StlClrClassLibrary geschrieben werden. Es werden zwei Assemblys an, um auf StlClrClassLibrary zuzugreifen. Die erste Assembly wird in C++ und in die zweite in C# geschrieben.
Wenn beide Assemblys in C++ geschrieben werden, können Sie auf die generische Schnittstelle eines Containers zugreifen, indem Sie seine generic_container-Typedef verwenden. Wenn Sie einen Container Typ cliext::vector<int> verfügen, dessen generische Schnittstelle ist: cliext::vector<int>::generic_container. Ebenso können Sie keinen Iterator über die generischen Schnittstelle abrufen, indem Sie die generic_iterator sind, wie in verwenden: cliext::vector<int>::generic_iterator.
Da diese Typdefinitionen in C++-Headerdateien deklariert werden, können Assemblys, die in anderen Sprachen geschrieben werden, nicht verwenden. Daher auf die generische Schnittstelle für cliext::vector<int> in C# oder in einer anderen .NET-Sprache zugreifen, verwenden Sie System.Collections.Generic.ICollection<int>. Um über dieser Auflistung durchlaufen, verwenden Sie eine foreach - Schleife.
Die folgende Tabelle zeigt die generische Schnittstelle, auf die jeder STL/CLR-Container implementiert:
STL/CLR-Container |
Generische Schnittstelle |
---|---|
dequeT <> |
ICollectionT <> |
hash_mapK <, V> |
IDictionaryK <, V> |
hash_multimapK <, V> |
IDictionaryK <, V> |
hash_multisetT <> |
ICollectionT <> |
hash_setT <> |
ICollectionT <> |
listT <> |
ICollectionT <> |
mapK <, V> |
IDictionaryK <, V> |
multimapK <, V> |
IDictionaryK <, V> |
multisetT <> |
ICollectionT <> |
Pflasterstein <> |
ICollectionT <> |
vectorT <> |
ICollectionT <> |
Hinweis
Da queue, priority_queue und stack keine Iteratoren Container unterstützen, implementieren sie nicht generische Schnittstellen und können nicht zugreifen assemblyübergreifendes sein.
Beispiel 1
Beschreibung
In diesem Beispiel deklarieren wir eine C++-Klasse, die private STL/CLR-Memberdaten enthält. Wir deklarieren dann öffentliche Methoden zum Zugriff auf die Privatsammlungen der Klasse. Wir führen sie auf zwei verschiedene Methoden, eine für C++-Clients und eine andere für .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 Klasse, die in diesem Beispiel 1. deklariert wird. Damit Clients verwenden diese Klassenbibliothek, 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 die parallelen Assemblys, finden Sie unter Erstellen von isolierten Anwendungen und parallelen Assemblys (C/C++).
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 Client eine C++-Headerdatei erstellt, der die Klassenbibliothek verwendet, die in Beispielen 1 und 2. erstellt wird. Dieser Client verwendet die generic_container-Typdefinitionen der STL/CLR-Container, um über den Containern 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 ein C#-Client erstellt, der die Klassenbibliothek verwendet, die in Beispielen 1 und 2. erstellt wird. Dieser Client verwendet die Methoden ICollection /CLR-Container der STL, um über den Containern 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;
}
}
}
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