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中的所有字节来更新整个记录。)

进一步澄清:

>p>我有一个简单的旧ANSI C DLL导出API,内部使用C++和Booo::进程::该函数需要在映射中创建一个项,然后返回一个句柄。如何在boost::interprocess::map中插入一些内容,然后将该实体的句柄返回给非C++用户,最好转换为
void*
unsigned long
?我所能做的似乎就是通过查找std::string键值从共享内存中获取内容,并将新记录写入内存。我希望能够保留对共享内存对象的引用

  • 如果我不能直接做到这一点,我将如何间接做到这一点?我想我可以保留一个非共享内存std::vector,并分配一个非共享内存std::string,其中包含areaKey的值,这是一个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;
    }