Ich bin ein wenig verwirrt durch die Semantik Heap und By-Value-versus-by-Referenz beteiligt einen std::string
Schlüssel und einen großen struct
Wert in einen Container wie boost::interprocess::map
.Wie kann ich ein undurchsichtiges Handle (void * oder dword) zurückgeben, das zu einem Wertelement zurückgeworfen werden kann, das in einer boost :: interprocess map gespeichert ist?
Hier ist meine Situation, und einige typedefs Ich verwende:
typedef std::string AreaKeyType;
typedef DATA_AREA_DESC AreaMappedType; // DATA_AREA_DESC is a big struct.
typedef std::pair<const AreaKeyType, AreaMappedType> AreaValueType;
typedef boost::interprocess::allocator<AreaValueType, boost::interprocess::managed_shared_memory::segment_manager> AreaShmemAllocator;
typedef boost::interprocess::map<AreaKeyType, AreaMappedType, std::less<AreaKeyType>, AreaShmemAllocator> AreaMap;
Hier ist, wie ich das Einfügen AreaValueType (das ist ein typedef für std :: pair):
AreaValueType A(areaKey, arearec);
anAreaMap->insert(A);
Ich glaube, der obige Code kopiert A, das ist ein std :: -Paar auf meinem lokalen Stapel (nicht gemeinsam genutzten Speicher) in einen gemeinsamen Speicherbereich. Kann ich den shared memory Bereich innerhalb der boost :: interprocess :: map Handle bekommen oder bin ich darauf beschränkt diesen Datensatz zurück zu holen und ihn ganz zu speichern? (Mit anderen Worten, kann ich etwas wie eine Struktur in eine Boost-Interprozess-Map speichern und dann ein einzelnes Byte innerhalb dieses Datensatzes aktualisieren, oder muss ich nur den gesamten Datensatz aktualisieren, indem ich alle Bytes in einer DATA_AREA_DESC-Struktur durch völlig neue ersetzt habe bytes)
Einige weitere Klärung.
ich habe eine einfache alte ANSI-C-DLL Export api, die C++ intern verwendet, und boost :: inter :: map. Es wird erwartet, dass die Funktion ein Element in der Map erstellt und dann ein Handle zurückgibt. Wie kann ich etwas in die boost :: interprocess :: map einfügen und dann ein Handle an diese Entität an Nicht-C++ - Benutzer übergeben, vorzugsweise an
void*
oderunsigned long
? Alles, was ich tun kann, ist, Sachen aus dem gemeinsamen Speicher zu holen, indem ich den Schlüsselwert std :: string nachschaue und einen neuen Datensatz in den Speicher schreibe. Ich möchte stattdessen in der Lage sein, einen Verweis auf das Shared Memory-Objekt zu behalten.Wenn ich das nicht direkt tun kann, wie würde ich es indirekt tun? Ich nehme an, ich könnte ein non-shared-memory std :: vector behalten und einen nicht-shared memory std :: string zuweisen, der den Wert von areaKey enthält, was eine std :: string ist, und dann eine Umwandlung von
void*
Element zurück aufstd::string
und dann verwenden, um einen Datensatz aus dem gemeinsamen Speicherbereich zu holen. Das alles scheint mehr Arbeit zu sein als unbedingt notwendig für etwas so elementares. Vielleicht ist boost :: interprocess :: map nicht die richtige Wahl für meine Anforderungen?
Was habe ich versucht? Das kompiliert, aber ich habe keine Ahnung, ob ich das richtig mache. Irgendwie fühle ich mich hässlich innen dereferencing ein ::iterator
von find
zurückgekehrt, und dann sofort unter seiner Adresse in etwa so:
void ** handle; // actually a parameter in my api.
*handle = (void*)&(*anAreaMap->find(areaKey));
aktualisieren Die oben genannten Arbeiten. Der sehr vernünftige Rat in der Antwort unten funktioniert jedoch nicht. Die Verwendung von boost :: interprocess :: string führt zu einem vollständigen und vollständigen Fehler und stürzt zur Laufzeit ab. Mit std :: string, das kein Recht auf Arbeit hat, außer die Autoren von Boost codierten std :: string Unterstützung vor allem, funktioniert wirklich gut.
gut, könnten Sie at() anstelle von find() verwenden, dann gäbe es keine Dereferenzierung :) – EHuhtala
Ich denke, Sie haben Recht. –