How to: 公開 (expose) 的組件的 STL/CLR 容器
STL/CLR 容器,例如list和map會實作為範本 ref 類別。 C + + 樣板會在編譯時期具現化,因為兩個完全相同的簽章,但位於不同組件的範本類別都是不同的型別。 這表示不能使用跨組件界限的樣板類別。
如果要讓共用組件交叉,STL/CLR 容器實作泛型介面ICollection<T>。 藉由使用這個泛型介面,支援泛用,包括 C++、 C# 和 Visual Basic 的所有語言都可以都存取 STL/CLR 容器。
本主題將說明如何顯示數個 STL/CLR 容器寫入名為 C++ 組件中的項目StlClrClassLibrary。 我們會示範兩個組件存取StlClrClassLibrary。 第一個組件是以 C++ 中,並在 C# 中的,第二個。
如果兩個組件撰寫 C++ 中,您可以使用存取容器的泛用介面其generic_container typedef。 比方說,如果您有容器型別的cliext::vector<int>,其泛用的介面將會是: cliext::vector<int>::generic_container。 同樣地,使用泛用介面上取得 iterator generic_iterator typedef,做為 in: cliext::vector<int>::generic_iterator。
因為這些檔的 typedef 也會在 C++ 標頭檔中宣告,以其他語言撰寫的組件無法使用它們。 因此,若要存取的泛用介面cliext::vector<int> C# 或任何其他中。NET 語言中,使用System.Collections.Generic.ICollection<int>。 若要逐一查看這個集合,請使用foreach迴圈。
下表列出每個 STL/CLR 容器會實作泛型介面:
STL/CLR 容器 |
泛用介面 |
---|---|
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> |
<T> 清單 |
ICollection <T> |
將對應的 < K V > |
IDictionary < K、 V > |
multimap < K、 V > |
IDictionary < K、 V > |
多重集 <T> |
ICollection <T> |
設定 <T> |
ICollection <T> |
向量 <T> |
ICollection <T> |
注意事項 |
---|
因為queue, priority_queue,以及stack容器不支援 iterator,它們不會實作泛型介面,且無法存取的跨組件。 |
範例 1
描述
在這個範例中,我們會宣告 C++ 類別,其中包含私用 STL/CLR 成員資料。 然後宣告來授與存取私用的集合類別的公用方法。 我們能在兩個不同的方式,一個用於 C++ 用戶端,另一個。NET 用戶端。
程式碼
// 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;
};
}
範例 2
描述
在這個範例中,我們會實作範例 1 中所宣告的類別。 為了讓用戶端使用這個類別庫,我們會使用資訊清單工具mt.exe若要將資訊清單檔內嵌至 DLL。 如需詳細資訊,請參閱程式碼註解。
如需有關的資訊清單工具和並排顯示組件的詳細資訊,請參閱建置 C/C++ 隔離應用程式和並存組件。
程式碼
// 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;
}
}
範例 3
描述
在這個範例中,我們建立一個使用範例 1 和 2 中所建立的類別程式庫的 C++ 用戶端。 此用戶端使用generic_container檔的 typedef 也之 STL/CLR 容器來逐一查看的容器,並顯示其內容。
程式碼
// 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
範例 4
描述
在這個範例中,我們可以建立使用範例 1 和 2 中所建立的類別程式庫 C# 用戶端。 此用戶端使用ICollection<T>的 STL/CLR 容器來逐一查看的容器,並顯示其內容的方法。
程式碼
// 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