C++ 如何返回一个不透明句柄(void*或dword),该句柄可以转换回存储在boost::进程间映射中的value元素?
在将C++ 如何返回一个不透明句柄(void*或dword),该句柄可以转换回存储在boost::进程间映射中的value元素?,c++,visual-c++,boost,visual-c++-2008,boost-interprocess,C++,Visual C++,Boost,Visual C++ 2008,Boost Interprocess,在将std::string键和大型struct值放入类似boost::interprocess::map的容器中时,涉及到堆、值和引用语义,这让我有点困惑 以下是我的情况,以及我正在使用的一些typedef: typedef std::string AreaKeyType; typedef DATA_AREA_DESC AreaMappedType; // DATA_AREA_DESC is a big struct. typedef std::pair<
std::string
键和大型struct
值放入类似boost::interprocess::map
的容器中时,涉及到堆、值和引用语义,这让我有点困惑
以下是我的情况,以及我正在使用的一些typedef:
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;
我相信上面的代码将本地(非共享内存)堆栈上的std::pair复制到共享内存区域。我可以在boost::interprocess::map中获得共享内存区域的句柄吗?或者我只能完整地获取该记录并将其存储起来吗?(换句话说,我可以将类似结构的内容存储到boost进程间映射中,然后更新该记录中的一个字节,还是只需通过用全新字节替换DATA_AREA_DESC struct中的所有字节来更新整个记录。)
进一步澄清:
void*
或unsigned long
?我所能做的似乎就是通过查找std::string键值从共享内存中获取内容,并将新记录写入内存。我希望能够保留对共享内存对象的引用
void*
项转换回std::string
,然后使用它从共享内存区域中取出一条记录。对于如此简单的事情来说,这一切似乎比严格必要的工作要多。也许boost::interprocess::map不适合我的需求find
返回的::迭代器时很难看,然后立即获取它的地址,就像这样:
void ** handle; // actually a parameter in my api.
*handle = (void*)&(*anAreaMap->find(areaKey));
更新上述功能。然而,下面答案中非常明智的建议并不奏效。使用boost::interprocess::string会导致运行时完全失败和崩溃。使用std::string,除非特别是Boost编码的std::string支持的作者,否则它无权工作。实际上,使用std::string效果很好。如果handle
被认为是共享内存中std::pair
的指针,那么只要areaKey
在映射中,您的代码就可以工作。除了不需要显式强制转换外,它没有任何问题(如果您确实需要强制转换,则首选static\u cast()
)
我没有使用过boost::interprocess
,但我认为您需要使用boost::interprocess::string
或std::basic_string
,并为您的密钥使用非默认分配器。除非boost::interprocess
在后台做了一些有趣的事情,否则使用std::string
会将指向本地内存(用于字符串缓冲区)的指针放入共享内存中,而这在另一个进程中是没有意义的
下面是一个使用带有字符串键的映射的测试程序:
#include <iostream>
#include <string>
#include <boost/foreach.hpp>
#include <boost/format.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/map.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
namespace bi = boost::interprocess;
#define SHARED_STRING 1 // set to 1 for interprocess::string, 0 for std::string
static const char *SHARED_MEMORY_NAME = "MySharedMemory";
static const char *SHARED_MAP_NAME = "MySharedMap";
int main(int argc, char *argv[]) {
#if SHARED_STRING
typedef bi::allocator<char, bi::managed_shared_memory::segment_manager> CharAllocator;
typedef bi::basic_string<char, std::char_traits<char>, CharAllocator> Key;
#else
typedef std::allocator<char> CharAllocator;
typedef std::basic_string<char, std::char_traits<char>, CharAllocator> Key;
#endif
typedef int Mapped;
typedef std::pair<const Key, Mapped> Value;
typedef bi::allocator<Value, bi::managed_shared_memory::segment_manager> MapAllocator;
typedef bi::map<Key, Mapped, std::less<Key>, MapAllocator> Map;
bi::managed_shared_memory *segment;
Map *map;
if (argc <= 1) {
// Create new shared memory segment.
bi::shared_memory_object::remove(SHARED_MEMORY_NAME);
segment = new bi::managed_shared_memory(bi::create_only, SHARED_MEMORY_NAME, 65536);
MapAllocator mapAllocator(segment->get_segment_manager());
map = segment->construct<Map>(SHARED_MAP_NAME)(std::less<Key>(), mapAllocator);
assert(map);
}
else {
// Open existing shared memory segment.
segment = new bi::managed_shared_memory(bi::open_only, SHARED_MEMORY_NAME);
map = segment->find<Map>(SHARED_MAP_NAME).first;
assert(map);
}
#if SHARED_STRING
CharAllocator charAllocator(segment->get_segment_manager());
#else
CharAllocator charAllocator;
#endif
while (true) {
std::string input;
if (!getline(std::cin, input))
break;
map->insert(std::make_pair(Key(input.begin(), input.end(), charAllocator), 0));
BOOST_FOREACH(const Value& value, *map)
std::cout << boost::format("('%s',%d)\n") % value.first % value.second;
}
delete segment;
bi::shared_memory_object::remove(SHARED_MEMORY_NAME);
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
名称空间bi=boost::进程间;
#定义共享_字符串1//对于进程间::字符串设置为1,对于std::字符串设置为0
静态常量char*SHARED\u MEMORY\u NAME=“MySharedMemory”;
静态常量char*SHARED\u MAP\u NAME=“MySharedMap”;
int main(int argc,char*argv[]){
#如果共享字符串
typedef bi::分配器CharAllocator;
typedef bi::基本_字符串键;
#否则
typedef std::分配器CharAllocator;
typedef std::基本_字符串键;
#恩迪夫
typedef int映射;
typedef std::对值;
typedef bi::分配器映射分配器;
typedef-bi::map;
bi::托管共享内存*段;
地图*地图;
if(argc get_segment_manager());
map=段->构造(共享映射名称)(std::less(),mapAllocator);
断言(map);
}
否则{
//打开现有共享内存段。
段=新bi::托管共享内存(bi::仅打开,共享内存\u名称);
映射=段->查找(共享映射名称);
断言(map);
}
#如果共享字符串
CharAllocator CharAllocator(段->获取段管理器());
#否则
CharAllocator CharAllocator;
#恩迪夫
while(true){
std::字符串输入;
如果(!getline(标准::cin,输入))
打破
映射->插入(std::make_pair(键(input.begin(),input.end(),charAllocator),0);
BOOST_FOREACH(常量值和值,*map)
当然,可以使用at()代替find()我不认为你是对的。我不需要在进程间共享未键入的值,我只需要在一个客户机或服务器内部提供一个非类型化的API,并且内部使用Boost C++ ++ API,它将被平直地降到DLL接口ABI的普通老C(<代码>应用程序二进制接口< /代码>)。目的。我知道你只需要一个普通的void*
作为你的句柄。我在第二段中想说的是,你的内部映射在共享它的进程之间无法正常工作,除非它的字符串键在进程之间是有效的,如果它是std::string
,它将无效。也就是说,如果你有两个进程试图在映射中查找值,或者一个进程插入值,另一个进程读取值,这可能无法使用普通的std::string
作为映射键
#include <iostream>
#include <string>
#include <boost/foreach.hpp>
#include <boost/format.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/map.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
namespace bi = boost::interprocess;
#define SHARED_STRING 1 // set to 1 for interprocess::string, 0 for std::string
static const char *SHARED_MEMORY_NAME = "MySharedMemory";
static const char *SHARED_MAP_NAME = "MySharedMap";
int main(int argc, char *argv[]) {
#if SHARED_STRING
typedef bi::allocator<char, bi::managed_shared_memory::segment_manager> CharAllocator;
typedef bi::basic_string<char, std::char_traits<char>, CharAllocator> Key;
#else
typedef std::allocator<char> CharAllocator;
typedef std::basic_string<char, std::char_traits<char>, CharAllocator> Key;
#endif
typedef int Mapped;
typedef std::pair<const Key, Mapped> Value;
typedef bi::allocator<Value, bi::managed_shared_memory::segment_manager> MapAllocator;
typedef bi::map<Key, Mapped, std::less<Key>, MapAllocator> Map;
bi::managed_shared_memory *segment;
Map *map;
if (argc <= 1) {
// Create new shared memory segment.
bi::shared_memory_object::remove(SHARED_MEMORY_NAME);
segment = new bi::managed_shared_memory(bi::create_only, SHARED_MEMORY_NAME, 65536);
MapAllocator mapAllocator(segment->get_segment_manager());
map = segment->construct<Map>(SHARED_MAP_NAME)(std::less<Key>(), mapAllocator);
assert(map);
}
else {
// Open existing shared memory segment.
segment = new bi::managed_shared_memory(bi::open_only, SHARED_MEMORY_NAME);
map = segment->find<Map>(SHARED_MAP_NAME).first;
assert(map);
}
#if SHARED_STRING
CharAllocator charAllocator(segment->get_segment_manager());
#else
CharAllocator charAllocator;
#endif
while (true) {
std::string input;
if (!getline(std::cin, input))
break;
map->insert(std::make_pair(Key(input.begin(), input.end(), charAllocator), 0));
BOOST_FOREACH(const Value& value, *map)
std::cout << boost::format("('%s',%d)\n") % value.first % value.second;
}
delete segment;
bi::shared_memory_object::remove(SHARED_MEMORY_NAME);
return 0;
}