0

QT初心者です。共有メモリ用に QT が提供する基本的な例を見てきましたが、共有メモリを使用して構造を共有したいと考えています。どうすれば達成できますか?

void Dialog::Send()
{
if (sharedMemory.isAttached())
    detach();
QBuffer buffer;
buffer.open(QBuffer::ReadWrite);
QDataStream out(&buffer);
out << structa->a;
out << structa->b;
out << structa->c;
int size = buffer.size();
  if (!sharedMemory.create(size))
{
    ui.label->setText(tr("Unable to create shared memory segment."));
    return;
}
sharedMemory.lock();
char *to = (char*)sharedMemory.data();
const char *from = buffer.data().data();
memcpy(to, from, qMin(sharedMemory.size(), buffersize));
sharedMemory.unlock();
}

Receive Function では、バッファ内のデータを正しく取得していますが、それを Struct veriable に変換できません。

void Dialog::Receive()
{   
if (!(sharedMemory.attach()))
{
    ui.label->setText(tr("Unable to attach to shared memory segment.\n" \
                         "Load an image first."));
    return;
}
QByteArray byteArray;
QBuffer buffer(&byteArray);
QDataStream in(&buffer);
TestStruct tmp;                                     //Re-make the struct
sharedMemory.lock();
buffer.setData((char*)sharedMemory.constData(), sizeof(tmp));
buffer.open(QBuffer::ReadOnly);
int nSize = ((buffer.size()));
memcpy(&tmp, buffer.data().data(), nSize);
qDebug()<< " tmp.a = "<<tmp.a;
qDebug()<< " tmp.b = "<<tmp.b;
qDebug()<< " tmp.c = "<< tmp.c;
sharedMemory.unlock();
sharedMemory.detach();
}
4

1 に答える 1

0

を使用して個々のフィールドを書き込んQDataStreamでいますが、 を使用して構造体として読み取りmemcpyます。これは問題を引き起こします!

書き込みと同じ方法でデータを読み取る必要があります。

TestStruct例 (と同じ型のメンバー a、b、および c があると仮定structa):

QBuffer buffer;
sharedMemory.lock();
buffer.setData(sharedMemory.constData(), sharedMemory.size());
sharedMemory.unlock();

buffer.open(QIODevice::ReadOnly);
QDataStream in(&buffer);
TestStruct tmp;
in >> tmp.a;
in >> tmp.b;
in >> tmp.c;
buffer.close();

更新:構造体に
単純なchars がある場合、 がないため、抽出コードは機能しませんoperator>>(QDataStream&, char&)。これを使用できます:

// Use intermediate qint8 (or quint8)
qint8 t;
in >> t;
char x = t;

完全な構造のシリアライズ

一度に完全な構造を書くことができます:

// Writing:
TestStruct structa; // Initialized as needed
QBuffer buffer;
buffer.open(QIODevice::WriteOnly);
buffer.write(&structa, sizeof(TestStruct));
buffer.close();

// Reading:
QBuffer buffer;
buffer.setData(sharedMemory.constData(), sharedMemory.size());
buffer.open(QIODevice::ReadOnly);
TestStruct out;
buffer.read(&out, sizeof(TestStruct));
buffer.close();

しかし、注意してください!これはおそらく有益ではありません!パディングの問題については、たとえばこの質問を参照してください。この方法はお勧めしません

一般的な Qt シリアライゼーション アプローチ

このブログにはかなり良いガイドがあります。Qt での一般的なシリアル化方法の基本を示します。

QVariant基本的な考え方は、オブジェクトをsにシリアライズすることです。は、 からのマップであるQVariantを含む多くの型を格納できます。したがって、階層構造を作成できます。QVariantMapQString => QVariant

これらQVariantの は、 を使用してシリアライズできますQDataStream

概要は次のとおりです。

// Enables << and >> for all QVariant supported types
template <typename T>
void operator << (QVariant &v, const T &d) {
    v = QVariant::fromValue<T>(d);
}
template <typename T>
void operator >> (const QVariant &v, T &d) {
    d = v.value<T>();
}

// Enable << and >> for your own type
void operator << (QVariant &v, const TestStruct &t) {
   QVariantMap m;
   m["a"] << t.a; // Re-use already defined operator <<
   m["b"] << t.b;
   m["c"] << t.c; 
   // ...
   v << m; // Put mapped custom type into a single QVariant
}
void operator >> (const QVariant &v, TestStruct &t) {
   QVariantMap m;
   // Load mapped type
   v >> m;
   m["a"] >> t.a; // Re-use already defined operator >>
   m["b"] >> t.b;
   m["c"] >> t.c; 
   // ...
}

これは次のように使用します。

// Writing
TestStruct structa;
QVariant v;
v << structa;
QBuffer buffer;
buffer.open(QIODevice::WriteOnly);
QDataStream str(&buffer);
str << v;

// Reading
QBuffer buffer;
buffer.setData(...);
buffer.open(QIODevice::ReadOnly);
QDataStream str(&buffer);
str >> v;
TestStruct structa;
v >> structa;
于 2016-05-24T09:13:48.987 に答える