首页 文章

如何返回可以转换为存储在boost :: interprocess映射中的值元素的不透明句柄(void *或dword)?

提问于
浏览
7

我对 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;

这是我如何插入AreaValueType(这是std :: pair的typedef):

AreaValueType A(areaKey, arearec);
 anAreaMap->insert(A);

我相信上面的代码将我在本地(非共享内存)堆栈上的std :: pair复制到共享内存区域 . 我可以在boost :: interprocess :: map中获取该共享内存区域的句柄,还是仅限于将该记录整回并整个存储? (换句话说,我可以将类似结构的东西存储到boost进程间映射中,然后更新该记录中的单个字节,或者我必须通过替换DATA_AREA_DESC结构中的所有字节来更新整个记录,全新字节) .

进一步澄清:

  • 我有一个普通的旧ANSI C DLL导出api,内部使用C和Boost :: interprocess :: map . 该函数应该在 Map 中创建一个项目,然后返回一个句柄 . 如何在boost :: interprocess :: map中插入一些东西,然后向非C用户返回该实体的句柄,最好转换为 void*unsigned long ?我所能做的就是通过查找std :: string键值从共享内存中获取内容,并将新记录写入内存 . 我希望能够保持对共享内存对象的引用 .

  • 如果我不能直接这样做,我将如何间接地做到这一点?我想我可以保留一个非共享内存std :: vector,并分配一个非共享内存std :: string,它保存areaKey的值,这是一个std :: string,然后执行 void* 的强制转换item返回 std::string 然后使用它从共享内存区域中取出一条记录 . 对于一些如此基本的东西来说,这似乎都是非常必要的工作 . 也许boost :: interprocess :: map不是我的要求的正确选择?

我试过了什么?这个,编译,但我不知道我是否正确这样做 . 不知何故,我觉得丑陋内部取消引用从 find 返回的 ::iterator ,然后立即采取其地址如下:

void ** handle; // actually a parameter in my api.
*handle = (void*)&(*anAreaMap->find(areaKey));

Update 以上作品 . 然而,下面答案中非常明智的建议不起作用 . 使用boost :: interprocess :: string会导致完整和完全失败并在运行时崩溃 . 使用std :: string,除非特别是Boost编码std :: string支持的作者,否则无权工作,实际上效果很好 .

1 回答

  • 1

    如果 handle 应该是共享内存中 std::pair 的指针,那么你的代码将起作用 provided 你知道 areaKey 在 Map 中 . 有's nothing wrong with it except you don' t需要显式演员(如果你做演员,那么 static_cast<void*>() 将是首选) .

    我没有使用 boost::interprocess 但是我认为你需要使用 boost::interprocess::stringstd::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;
    }
    

    不带参数运行它来创建一个新的共享内存段,并至少有一个参数来打开一个现有的共享内存段(无参数调用必须已经在运行) . 在这两种情况下,程序将迭代地从 stdin 读取一个键,在 Map 中插入一个条目,并将内容写入 stdout .

相关问题