PDA

View Full Version : How do I read shared memory data written by Qt using boost ?



rawfool
15th May 2013, 07:10
I'm writing a string into QSharedMemory and after writing, I need to read it from boost program. I tried this, but didn't work.
I read the data in shared memory from the same Qt program, and I see the string.

Below is Qt program, from which I'm writing into shared memory with key ShrdMem
// Slot, which is invoked on click of button.
void CDialog::loadString()
{
if(sharedMemory.isAttached())
{
if(!sharedMemory.detach())
{
lbl->setText("Unable to detach from Shared Memory");
return;
}
}

char sString[] = "my string";

QBuffer buffer;
buffer.open(QBuffer::ReadWrite);

QDataStream out(&buffer);
out << sString;

int size = buffer.size();
qDebug() << size;

if(!sharedMemory.create(size))
{
lbl->setText("Unable to create shared memory segment");
qDebug() << lbl->text();
}
sharedMemory.lock();
char *to = (char *) sharedMemory.data();
const char *from = buffer.data();
memcpy(to, from, qMin(sharedMemory.size(), size));
sharedMemory.unlock();

char * str;
QDataStream in(&buffer);
sharedMemory.lock();
buffer.setData((char *)sharedMemory.constData(), sharedMemory.size());
buffer.open(QBuffer::ReadOnly);
in >> str;
sharedMemory.unlock();
qDebug() << str;
}
I'm trying to read the ShrdMem using Boost as shown below.
//NQShrdMem.cpp
int main()
{
boost::interprocess::shared_memory_object shdmem(boost::interprocess::open_only, "ShrdMem", boost::interprocess::read_only);

boost::interprocess::offset_t size;
if (shdmem.get_size(size))
std::cout << "Shared Mem Size: " << size << std::endl;

boost::interprocess::mapped_region region2(shdmem, boost::interprocess::read_only);
char *i2 = static_cast<char *>(region2.get_address());
std::cout << i2 << std::endl;
return 0;
}

I'm compiling the Boost program in cygwin, using g++:

g++ -I /cygdrive/c/boost/boost_1_53_0/ NQShrdMem.cpp -o NQShrdMem /cygdrive/c/boost_lib/boost/bin.v2/libs/date_time/build/gcc-mingw-4.7.2/release/link-static/threading-multi/libboost_date_time-mgw47-mt-1_53.a

Kindly help me. Thank you.

ChrisW67
15th May 2013, 07:41
You are using QDataStream in a setting where you are expecting a non-Qt program to read the data. There will be more data in the output stream than you are likely expecting to see: you need to account for that at the receiver. Read the docs for QDataStream::operator<<(const char *s) carefully or do not use QDataStream.

BTW: It doesn't work is not a useful description. It helps if you let us know what's not working? What did you expect to happen? What is happening? etc.

rawfool
15th May 2013, 08:05
You are using QDataStream in a setting where you are expecting a non-Qt program to read the data.Kindly tell me what I have to use ? I read the docs but couldn't get much.


what's not working? What did you expect to happen? What is happening?1. First, I'm executing the Qt program to write to shared memory.
2. Then executing the Non-Qt(Boost program).
3. Expecting the Boost program to display size (std::cout << "Shared Mem Size: " << size << std::endl; ) and string (std::cout << i2 << std::endl;). But no result, in cygwin the promt appears again.

Thank you.

ChrisW67
15th May 2013, 08:23
If you want total control of the bytes placed in the shared memory segment then you can either put them into a QByteArray directly or you can use QIODevice::write() against a QBuffer.

I suggest you dump buffer.data().toHex() and inspect what QDataStream actually put into the buffer. Your generic C++ is expecting the buffer to start with a '\0' terminated string but it does not; it starts with a 4-byte length integer as described in the QDataStream docs. For a short string 3 of those 4 bytes will be '\0', terminating any string you read. The actual string component may also not have the terminating '\0' any longer.

rawfool
15th May 2013, 09:20
I tried changing QByteArray directly instead of QBuffer and dumped data to shared memory.
I tried to read the same using qDebug(), which gave me the same string that I'm passing (my string) but with lot of zeroes appended.

// Hex Value
6d7920737472696e6700000000000000000000000000000000 00(so many zeroes, so I deleted here.)

But still I'm not able to get the same in Non-Qt(Boost) program's output.

I did the following changes in Qt program

void CDialog::loadFromFile()
{
if(sharedMemory.isAttached())
{
if(!sharedMemory.detach())
{
lbl->setText("Unable to detach from Shared Memory");
return;
}
}

char sString[] = "my string";

QByteArray out(sString, 10);

int size = out.size();
qDebug() << size;

if(!sharedMemory.create(size))
{
lbl->setText("Unable to create shared memory segment");
qDebug() << lbl->text();
}
sharedMemory.lock();
char *to = (char *) sharedMemory.data();
const char *from = out.data();
memcpy(to, from, qMin(sharedMemory.size(), size));
sharedMemory.unlock();

QByteArray in;
sharedMemory.lock();
in.setRawData((char *)sharedMemory.constData(), sharedMemory.size());
sharedMemory.unlock();
qDebug() << in.toHex();
}

Thank you for helping.

anda_skoa
15th May 2013, 17:24
3. Expecting the Boost program to display size (std::cout << "Shared Mem Size: " << size << std::endl; ) and string (std::cout << i2 << std::endl;). But no result, in cygwin the promt appears again.


If you don't get the size output, doesn't that mean that shared_memory_object::get_size() has returned false?
Wouldn't that indicate that you didn't access the shared memory correctly?

Cheers,
_

rawfool
16th May 2013, 06:47
Yeah, but I called the shared memory using the same key specified in the Qt program. I think that is the only way to access a shared memory. Is there anything that needs to be done ?
Thank you.

ChrisW67
16th May 2013, 08:16
On my Linux system QSharedMemory creates a file with the path given by key(). The generated key will be in /tmp. So for setKey("FOO") I get file "/tmp/qipc_sharedmemory_FOOfeab40e1fca77c7360ccca1481bb8 ba5f919ce3a" (a predictable name). If you use setNativeKey() you can explicitly direct the file name and location.

On the same system Boost will look for the specified shared memory block name under /dev/shm. So,


shared_memory_object shdmem(open_only, "FOO", boost::interprocess::read_only);

looks for, and fails to find, "/dev/shm/FOO"

I expect that is what is going on with you. However, we are not privy to the behaviours and limits of Boost in your Cygwin environment.

rawfool
16th May 2013, 08:59
Now in addition to that, I created a shared memory using Boost shared memory in Qt, wrote a string into that. Then tried to access the same using another Boost program compiled in Cygwin-g++. Here get_size() is giving 0 and string is not being read. But surprising thing is, if I delete the same shared memory (for the specified key) using remove statement in cygwin-g++ program, it's getting deleted.


bool isRemoved = boost::interprocess::shared_memory_object::remove("ShrdMem");
std::cout << "Value = " << isRemoved << std::endl; // Value = 1

Writing in Qt(using QSharedMemory), then reading using Boost shared memory - Not working as expected
Writing in Qt(using boost shared memory), then reading using Boost shared memory - Not working as expected
Writing in Boost, reading in Boost(both compiled & run in cygwin-g++) - Working fine (tested to read the string/int value).

Any help pls. Thank you.

ChrisW67
16th May 2013, 10:32
Writing in Qt(using boost shared memory), then reading using Boost shared memory - Not working as expected
Writing in Boost, reading in Boost(both compiled & run in cygwin-g++) - Working fine (tested to read the string/int value).

These are identical options. You don't write "in Qt(using boost shared memory)"... Qt is not a programming language. You write in C++, just like the other option.

I am assuming that your Qt application is not built in the Cygwin environment, i.e. it is native Windows, and that the shared memory environment that Cygwin gives its applications does not use Windows shared memory mechanisms. Consequently they do not meet in the middle.

Why are you using Cygwin anyway?

rawfool
16th May 2013, 11:45
I'm developing a GUI application, which needs communication with other process(built using Visual C++). I'm developing my app in Qt and trying to emulate the other process shared memory using boost, so just thought to do it Cygwin, thinking shared memory can be accessed commonly which requires a key and the key is unique.

The objective is to set-up a shared memory communication between two processes (one developed using Qt & other using Visual C++.
I'm trying to get one of the below mentioned two options to workout -
1. Using QSharedMemory from my side(GUI) and interacting with other process which is using Boost.
2. Using Boost interprocess in Qt since the other process too is using Boost.

Thank you.

rawfool
17th May 2013, 08:10
I solved the issue.

As ChrisW67 mentioned, the problem is in meeting point. May be the Cygwin-g++ program was looking in other folder (may be /tmp/ as mentioned above by @ChrisW67).
I created a Non-Qt C++ program, using Qt creator and read the shared memory using Boost ipc. It worked fine, I was able to read the string that I wrote in Qt program(Boost Shared memory).

Thank you ChrisW67 & anda_skoa