Copy std::vector to boost::interprocess::vector



我想使用boost intercess共享对象的向量。对象来自以下结构:

struct Foo
    {
        int id;
        float time;
        bool isFoo;
        float myArray[7];
        std::vector<int> vectorData;
    };

我正在创建Boost Inter Process分配器和间处理向量:

typedef allocator<Foo, managed_shared_memory::segment_manager>  FooAllocator;
typedef std::vector<Foo, FooAllocator> FooVector;

在我的主函数中,我基于:

初始化内存段,分配器和向量

Boost->在共享内存中创建向量

so:

managed_shared_memory mem_segment(open_or_create, "MemShare", 65536);
const FooAllocator alloc_inst(mem_segment.get_segment_manager());
fooVector = mem_segment.find_or_construct<FooVector>("FooVector")(alloc_inst);

现在,这适用于FOO结构中的每个数据类型,除了向量。因此,如果我尝试分享这一点,我会从FOO中获得所有成员,对于向量数据,我将获得"未定义的内存位置"我知道不能直接共享std :: vector。因此,我使用boost ::我创建了新的foo结构:

struct FooInter
    {
        int id;
        float time;
        bool isFoo;
        float myArray[7];
        MyVector* pointcloud;
    };

myVector在哪里:

typedef allocator<int, managed_shared_memory::segment_manager> VectorAllocator;
typedef boost::interprocess::vector<int, VectorAllocator> MyVector;

我正在为MyVector分配内存,

const VectorAllocator vec_alloc_inst(mem_segment.get_segment_manager());
MyVector* tmpVec = mem_segment.construct<MyVector>("MyVector")(vec_alloc_inst);

那么我现在尝试做的就是将foo映射到foointer。我正在将矢量数据映射到循环中:

    for (int t = 0; t < foo.vectorData.size()-1; t++) {
        tmpVec->push_back(foo.vectorData[t]);
    }

然后将TMPVEC复制到foointer.vectordata:

memcpy(fooInter.pointcloud, tmpVec, sizeof(int) * tmpVec->size());

这有效,但不适合foo.vectordata的整体尺寸。因此,它适用于100个项目,但是如果我使用foo.vectordata.size((,它将返回不良内存salroc。

有人可以帮助我。我需要知道分享这种类型结构的正确方法。我觉得我正在做的事情是完全错误的。也许我需要将向量序列化为字符串或类似的内容。

编辑:

基于sehe的答案:

我有类型的对象msg:

struct Foo
    {
        int id;
        float time;
        bool isFoo;
        float myArray[7];
        std::vector<int> pointcloud;
    };

我需要在Inter_foos中传递该对象。因此,在SEHE的代码中:

int main() {
    auto segment = Shared::open();
    auto& inter_foos = *segment.find_or_construct<InterFoos>("InterFoos")(segment.get_segment_manager());
    // you can directly append to the shared memory vector
    int nextid = inter_foos.size();
    //instead of this
    inter_foos.push_back({++nextid, 0, true, {.1,.2,.3,.4,.5,.6,.7}, Ints ({10,20,30}, segment.get_segment_manager()) });
    //i need this
        inter_foos.push_back({msg.id, msg.time, true, msg.myArray, Ints (msg.pointcloud, segment.get_segment_manager()) });
    //i can't pass msg.poincloud to this object!!!
    // or copy from a non-shared vector:
    std::vector<Foo> const local {
        {++nextid, 0, true, {.1,.2,.3,.4,.5,.6,.7}, {10,20,30} },
        {++nextid, 1, true, {.2,.3,.4,.5,.6,.7,.8}, {20,30,40} },
        {++nextid, 2, true, {.3,.4,.5,.6,.7,.8,.9}, {30,40,50} },
    };
    for (auto& local_foo : local)
        inter_foos.emplace_back(local_foo);
    // print the current contents
    for (auto& foo : inter_foos)
        std::cout << foo << "n"; 
}

您可以使用

的方法
  • 制作boost的非共享副本::概要共享内存对象
  • boost :: Intercess scoped_allocator和不共享内存中的容器的容器

请参阅此演示

活在coliru

#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/container/scoped_allocator.hpp>
#include <iostream>
#include <vector>
namespace Shared {
    namespace bip = boost::interprocess;
    namespace bc  = boost::container;
    using Segment                     = bip::managed_shared_memory;
    using Manager                     = Segment::segment_manager;
    template <typename T> using Alloc = bc::scoped_allocator_adaptor<bip::allocator<T, Manager> >;
    template <typename T> using Vector= bip::vector<T, Alloc<T> >;
    Segment open() { return { bip::open_or_create, "MySharedMemory", 10ul<<20 }; }
    template <typename Alloc = Alloc<void> >
    struct Foo {
        using allocator_type = typename Alloc::template rebind<Foo>::other;
        using Ints = bip::vector<int, typename Alloc::template rebind<int>::other>;
        Foo(int id, float time, bool isFoo = false, std::initializer_list<float> floats = {}, Ints data = {})
            : id(id), time(time), isFoo(isFoo), vectorData(std::move(data))
        {
            std::copy_n(floats.begin(), std::min(floats.size(), 7ul), myArray);
        }
        template <typename OA, typename A>
        Foo(Foo<OA> const& other, A alloc = {}) 
            : id(other.id), time(other.time), isFoo(other.isFoo),
              vectorData(other.vectorData.begin(), other.vectorData.end(), alloc)
        {
            std::copy(std::begin(other.myArray), std::end(other.myArray), myArray);
        }
        int   id;
        float time;
        bool  isFoo;
        float myArray[7] = {};
        Ints  vectorData;
    };
    template <typename A>
    std::ostream& operator<<(std::ostream& os, Foo<A> const& f) {
        os << "{" 
           << f.id << ", "
           << std::fixed << f.time << ", "
           << std::boolalpha << f.isFoo << ", "
           << "[";
        std::copy(std::begin(f.myArray), std::end(f.myArray), std::ostream_iterator<float>(std::cout, ";"));
        os << "], [";
        std::copy(std::begin(f.vectorData), std::end(f.vectorData), std::ostream_iterator<int>(std::cout, ";"));
        return os << "] }";
    }
}
using Foo       = Shared::Foo<std::allocator<void> >;
using InterFoo  = Shared::Foo<>;
using InterFoos = Shared::Vector<InterFoo>;
using Ints      = Shared::Vector<int>;
int main() {
    auto segment = Shared::open();
    auto& inter_foos = *segment.find_or_construct<InterFoos>("InterFoos")(segment.get_segment_manager());
    // you can directly append to the shared memory vector
    int nextid = inter_foos.size();
    inter_foos.push_back({++nextid, 0, true, {.1,.2,.3,.4,.5,.6,.7}, Ints ({10,20,30}, segment.get_segment_manager()) });
    // or copy from a non-shared vector:
    std::vector<Foo> const local {
        {++nextid, 0, true, {.1,.2,.3,.4,.5,.6,.7}, {10,20,30} },
        {++nextid, 1, true, {.2,.3,.4,.5,.6,.7,.8}, {20,30,40} },
        {++nextid, 2, true, {.3,.4,.5,.6,.7,.8,.9}, {30,40,50} },
    };
    for (auto& local_foo : local)
        inter_foos.emplace_back(local_foo);
    // print the current contents
    for (auto& foo : inter_foos)
        std::cout << foo << "n"; 
}

打印:

{1, 0.000000, true, [0.100000;0.200000;0.300000;0.400000;0.500000;0.600000;0.700000;], [10;20;30;] }
{2, 0.000000, true, [0.100000;0.200000;0.300000;0.400000;0.500000;0.600000;0.700000;], [10;20;30;] }
{3, 1.000000, true, [0.200000;0.300000;0.400000;0.500000;0.600000;0.700000;0.800000;], [20;30;40;] }
{4, 2.000000, true, [0.300000;0.400000;0.500000;0.600000;0.700000;0.800000;0.900000;], [30;40;50;] }

第二次运行:

{1, 0.000000, true, [0.100000;0.200000;0.300000;0.400000;0.500000;0.600000;0.700000;], [10;20;30;] }
{2, 0.000000, true, [0.100000;0.200000;0.300000;0.400000;0.500000;0.600000;0.700000;], [10;20;30;] }
{3, 1.000000, true, [0.200000;0.300000;0.400000;0.500000;0.600000;0.700000;0.800000;], [20;30;40;] }
{4, 2.000000, true, [0.300000;0.400000;0.500000;0.600000;0.700000;0.800000;0.900000;], [30;40;50;] }
{5, 0.000000, true, [0.100000;0.200000;0.300000;0.400000;0.500000;0.600000;0.700000;], [10;20;30;] }
{6, 0.000000, true, [0.100000;0.200000;0.300000;0.400000;0.500000;0.600000;0.700000;], [10;20;30;] }
{7, 1.000000, true, [0.200000;0.300000;0.400000;0.500000;0.600000;0.700000;0.800000;], [20;30;40;] }
{8, 2.000000, true, [0.300000;0.400000;0.500000;0.600000;0.700000;0.800000;0.900000;], [30;40;50;] }

范围分配器

请注意:

    for (auto& local_foo : local)
        inter_foos.emplace_back(local_foo);

由于范围的范围分配器而受支持并通过Boost的容器实现来支持和传递。如果您不使用它,则看起来像这样: Live on Coliru

template <typename T> using Alloc = bip::allocator<T, Manager>;
// ...
for (auto& local_foo : local)
    inter_foos.emplace_back(local_foo, segment.get_segment_manager());

¹使用映射文件,因为在Coliru上不支持共享内存

我无法想象使用memcpy复制MyVector的工作状况很好。当然您需要的是:

void FooInter::setVector(const std::vector<int>& vec) {
    const VectorAllocator vec_alloc_inst(mem_segment.get_segment_manager());
    const auto tmp = mem_segment.construct<MyVector>("MyVector")(vec_alloc_inst);
    tmp->insert(tmp->begin(), vec.begin(), vec.end());
    pointcloud = tmp;
}

换句话说,构造由pointcloud指向的对象,然后插入其中。

最新更新