Generics Collections TDictionary (C++)
Contents
Description
This example shows how to handle Delphi generics from a C++ application.
To build and test this example:
- Create a Delphi package where you can instantiate a TDictionary:
- Create a new Delphi package, and save it as "DelphiPackage".
- Add a new Delphi unit to your package, and save this unit as "DelphiUnit".
 
- Create a C++ console application to load and show your Delphi resource string:
- On the Projects Window, right-click your project group and select Add New Project.
- On the New Items dialog box, select C++Builder Projects on the tree view and, on the list of C++Builder projects, select Console Application and click OK.
- On the New Console Application dialog box that opens, click OK to use the default C++ console application settings.
- Save your main C++ file as "main.cpp", your precompiled header file as "CppApplicationPCH.h", and your project as "CppApplication".
- Select Project > Options > C++ Linker and enable the "Link with the Delphi Runtime Library" option.
 
Code
Copy the following code in your DelphiUnit.pas file:
unit DelphiUnit;
interface
uses
  System.Generics.Collections;
type
  TCity = class
    Country: String;
    Latitude: Double;
    Longitude: Double;
  end;
  // You cannot use TDictionary<String, TCity> in C++ unless you first
  // instantiate it in Delphi as follows:
  CityDictionary = class(TDictionary<String, TCity>)
  end;
implementation
end.
Then right-click your DelphiPackage project on the Project Manager and select Build.
Add the generated Delphi package library file to your C++ console application:
- Right-click your CppApplication project on the Project Manager and select Add.
- On the dialog box that opens, select the DelphiPackage.lib file that you previously built and click OK. You may find this file inside "C:\Users\Public\Documents\Embarcadero\Studio\37.0\Dcp".
- Note: If you cannot see the expected file, ensure that the file filter in the dialog box is "Any file (*.*)".
 
Copy the following code in your main.cpp file:
#pragma hdrstop
#pragma argsused
#ifdef _WIN32
#include <tchar.h>
#else
  typedef char _TCHAR;
  #define _tmain main
#endif
#include <iostream>
#include <DelphiUnit.hpp>
const double EPSILON = 0.0000001;
 int _tmain(int argc, _TCHAR* argv[]) 
{
    // Create the dictionary.
    TDictionary__2<UnicodeString, TCity*>* dictionary = new TDictionary__2<UnicodeString, TCity*>(0);
    TCity* city;
    // Add some key-value pairs to the dictionary.
    city = new TCity;
    city->Country = "Romania";
    city->Latitude = 47.16;
    city->Longitude = 27.58;
    dictionary->Add("Iasi", city);
    city = new TCity;
    city->Country = "United Kingdom";
    city->Latitude = 51.5;
    city->Longitude = -0.17;
    dictionary->Add("London", city);
    city = new TCity;
    city->Country = "Argentina";
    city->Latitude = 0;             // Wrong coordinates
    city->Longitude = 0;    // on purpose.
    dictionary->Add("Buenos Aires", city);
    // Display the current number of key-value entries.
    std::wcout << "Number of pairs in the dictionary: " << dictionary->Count << "." << std::endl;
    // Try looking up "Iasi".
    if (dictionary->TryGetValue("Iasi", city))
            std::wcout << "Iasi is located in " << city->Country
                       << " with latitude = " << city->Latitude
                       << " and longitude = " << city->Longitude
                       << "." << std::endl;
    else
        std::wcout << "Could not find Iasi in the dictionary." << std::endl;
    // Remove the "Iasi" key from the dictionary.
    dictionary->Remove("Iasi");
    // Make sure that the capacity of the dictionary is set to the number of entries.
    dictionary->TrimExcess();
    // Test if "Iasi" is a key in the dictionary.
    if (dictionary->ContainsKey("Iasi"))
        std::wcout << "The key \"Iasi\" is in the dictionary." << std::endl;
    else
        std::wcout << "The key \"Iasi\" is not in the dictionary." << std::endl;
    if (dictionary->ContainsKey("London")) {
        // Test how (United Kingdom, 51.5, -0.17) is a value in the dictionary...
        dictionary->TryGetValue("London", city);
        if (city->Country == "United Kingdom" && (city->Latitude - 51.5) < EPSILON && (city->Longitude - -0.17) < EPSILON)
            std::wcout << "The value (United Kingdom, 51.5, -0.17) is in the dictionary." << std::endl;
        else
            std::wcout << "Error: The value (United Kingdom, 51.5, -0.17) is not in the dictionary." << std::endl;
        // ...but ContainsValue returns False if passed a different instance of
        // TCity with the same data, as different instances have different references.
        city = new TCity;
        city->Country = "United Kingdom";
        city->Latitude = 51.5;
        city->Longitude = -0.17;
        if (dictionary->ContainsValue(city))
            std::wcout << "Error: A new instance of TCity with values (United Kingdom, 51.5, -0.17) matches an existing instance in the dictionary." << std::endl;
        else
            std::wcout << "A new instance of TCity with values (United Kingdom, 51.5, -0.17) does not match any existing instance in the dictionary." << std::endl;
        delete city;
    }
    else {
        std::wcout << "Error: The key \"London\" is not in the dictionary." << std::endl;
    }
    // Update the coordinates to the correct ones.
    city = new TCity;
    city->Country = "Argentina";
    city->Latitude = -34.6;
    city->Longitude = -58.45;
    dictionary->AddOrSetValue("Buenos Aires", city);
    // Generate the exception "Duplicates not allowed".
    try {
            dictionary->Add("Buenos Aires", city);
    } catch (Exception &e) {
            std::wcout << "Could not add entry. Duplicates are not allowed." << std::endl;
    }
    // Display all countries.
    std::wcout << "All countries:" << std::endl;
    DynamicArray<TCity*> cityValues = dictionary->Values->ToArray();
    const int cityCount = cityValues.get_length();
    for (int i = 0; i < cityCount; i++) {
        std::wcout << cityValues[i]->Country << std::endl;
    }
    // Iterate through all keys in the dictionary and display their coordinates.
    std::wcout << "All cities and their coordinates:" << std::endl;
    DynamicArray<UnicodeString> cityKeys = dictionary->Keys->ToArray();
    for (int i = 0; i < cityCount; i++) {
        dictionary->TryGetValue(cityKeys[i], city);
        std::wcout << cityKeys[i] << ": " << city->Latitude << ", " << city->Longitude << std::endl;
    }
    // Clear all entries in the dictionary.
    dictionary->Clear();
    // There should be no entries at this point.
    std::wcout << "Number of key-value pairs in the dictionary after cleaning: " << dictionary->Count << std::endl;
    std::cin.get();
    return 0;
}
Now you can run your C++ console application. A console should open and display the following output:
Number of pairs in the dictionary: 3. Iasi is located in Romania with latitude = 47.16 and longitude = 27.58. The key "Iasi" is not in the dictionary. The value (United Kingdom, 51.5, -0.17) is in the dictionary. A new instance of TCity with values (United Kingdom, 51.5, -0.17) does not match any existing instance in the dictionary. Could not add entry. Duplicates are not allowed. All countries: United Kingdom Argentina All cities and their coordinates: London: 51.5, -0.17 Buenos Aires: -34.6, -58.45 Number of key-value pairs in the dictionary after cleaning: 0
Uses
- System.Generics.Collections.TDictionary ( fr | de | ja )
- System.Generics.Collections.TDictionary.Keys ( fr | de | ja )
- System.Generics.Collections.TDictionary.Values ( fr | de | ja )
- System.Generics.Collections.TDictionary.Add ( fr | de | ja )
- System.Generics.Collections.TDictionary.AddOrSetValue ( fr | de | ja )
- System.Generics.Collections.TDictionary.Clear ( fr | de | ja )
- System.Generics.Collections.TDictionary.ContainsKey ( fr | de | ja )
- System.Generics.Collections.TDictionary.ContainsValue ( fr | de | ja )
- System.Generics.Collections.TDictionary.Remove ( fr | de | ja )
- System.Generics.Collections.TDictionary.TrimExcess ( fr | de | ja )