방법: 어셈블리에서 STL/CLR 컨테이너 노출

템플릿 ref 클래스와 같은 listmap STL/CLR 컨테이너로 구현됩니다. C++ 템플릿은 컴파일 시간에 인스턴스화되므로 시그니처가 정확히 동일하지만 어셈블리가 다른 두 템플릿 클래스는 실제로 다른 형식입니다. 즉, 어셈블리 경계를 넘어 템플릿 클래스를 사용할 수 없습니다.

어셈블리 간 공유를 가능하게 하기 위해 STL/CLR 컨테이너는 제네릭 인터페이스 ICollection<T>를 구현합니다. 이 제네릭 인터페이스를 사용하면 C++, C# 및 Visual Basic을 비롯한 제네릭을 지원하는 모든 언어가 STL/CLR 컨테이너에 액세스할 수 있습니다.

이 항목에서는 이름이 C StlClrClassLibrary++ 어셈블리로 작성된 여러 STL/CLR 컨테이너의 요소를 표시하는 방법을 보여 줍니다. 액세스할 StlClrClassLibrary두 개의 어셈블리를 보여 드립니다. 첫 번째 어셈블리는 C++로 작성되고 두 번째 어셈블리는 C#으로 작성됩니다.

두 어셈블리가 모두 C++로 작성된 경우 typedef를 사용하여 generic_container 컨테이너의 제네릭 인터페이스에 액세스할 수 있습니다. 예를 들어 형식 cliext::vector<int>의 컨테이너가 있는 경우 제네릭 인터페이스는 다음과 cliext::vector<int>::generic_container같습니다. 마찬가지로 다음과 같이 typedef를 사용하여 generic_iterator 제네릭 인터페이스를 통해 반복기를 가져올 수 있습니다 cliext::vector<int>::generic_iterator.

이러한 typedef는 C++ 헤더 파일에서 선언되므로 다른 언어로 작성된 어셈블리는 사용할 수 없습니다. 따라서 C# 또는 다른 .NET 언어의 제네릭 인터페이스에 cliext::vector<int> 액세스하려면 .를 사용합니다 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>
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>

참고 항목

queue, priority_queuestack 컨테이너는 반복기를 지원하지 않으므로 제네릭 인터페이스를 구현하지 않으며 어셈블리 간 액세스가 불가능합니다.

예 1

설명

이 예제에서는 프라이빗 STL/CLR 멤버 데이터를 포함하는 C++ 클래스를 선언합니다. 그런 다음 공용 메서드를 선언하여 클래스의 프라이빗 컬렉션에 대한 액세스 권한을 부여합니다. 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++ 격리된 애플리케이션 및 Side-by-side 어셈블리 빌드를 참조 하세요.

코드

// 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 STL/CLR 컨테이너의 typedef를 사용하여 컨테이너를 반복하고 해당 콘텐츠를 표시합니다.

코드

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

출력

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

출력

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

참고 항목

STL/CLR 라이브러리 참조