Send data between processes via QSharedMemory



  • Hello,

    I'm need to communicate with another process in OS.
    First process I would like to write on Qt (5.6.1). Second process on Visual Studio 2013 on WinAPI. I think that QSharedMemory is a good way for this.

    I used Shared Memory Example. It's correctly work in single process.

    Already I used Creating Named Shared Memory example from MSDN. It's also correctly work.

    But I can't transfer data from Qt application to WinAPI application. Qt application is correctly write data and I can read it in Qt application, but in WinAPI application is not possible to connect to shared memory and read it. Error: Could not open file mapping object.

    May be there is more detailed example for QSharedMemory?
    What is a problem here?

    My source code is bellow.
    Creating shared memory:

    Dialog::Dialog(QWidget *parent) :
        QDialog(parent),
        ui(new Ui::Dialog),
        sharedMemory("Global\\SharedMemoryExample")
    {
        ui->setupUi(this);
    }
    

    For write data to shared memory:

    void Dialog::on_writeButton_clicked()
    {
        QString data = ui->bufferLineEdit->text();
        if(sharedMemory.isAttached())
            sharedMemory.detach();
    
        QBuffer buffer;
        buffer.open(QBuffer::ReadWrite);
        QDataStream out(&buffer);
        out << data;
        int size = buffer.size();
    
        if(!sharedMemory.create(size))
        {
            ui->bufferLineEdit->setText("ERROR: Shared Memory not created");
            return;
        }
        sharedMemory.lock();
        char *to = (char*)sharedMemory.data();
        const char *from = buffer.data().data();
        memcpy(to, from, qMin(sharedMemory.size(), size));
        sharedMemory.unlock();
    }
    

    For read shared memory:

    void Dialog::on_readButton_clicked()
    {
        ui->bufferLineEdit->clear();
        if (!sharedMemory.isAttached())
        {
            ui->bufferLineEdit->setText("ERROR: Shared Memory not attached");
            return;
        }
        QBuffer buffer;
        QDataStream in(&buffer);
        QString data;
        data.clear();
    
        sharedMemory.lock();
        buffer.setData((char*)sharedMemory.constData(), sharedMemory.size());
        buffer.open(QBuffer::ReadOnly);
        in >> data;
        sharedMemory.unlock();
    
        sharedMemory.detach();
        ui->bufferLineEdit->setText(data);
    }
    

    And second WinApi application:

    #include <windows.h>
    #include <stdio.h>
    #include <conio.h>
    #include <tchar.h>
    #pragma comment(lib, "user32.lib")
    
    #define BUF_SIZE 256
    TCHAR szName[]=TEXT("Global//SharedMemoryExample");
    
    int _tmain()
    {
       HANDLE hMapFile;
       LPCTSTR pBuf;
    
       hMapFile = OpenFileMapping(
                       FILE_MAP_ALL_ACCESS,   // read/write access
                       FALSE,                 // do not inherit the name
                       szName);               // name of mapping object
    
       if (hMapFile == NULL)
       {
          _tprintf(TEXT("Could not open file mapping object (%d).\n"),
                 GetLastError());
          return 1;
       }
    
       pBuf = (LPTSTR) MapViewOfFile(hMapFile, // handle to map object
                   FILE_MAP_ALL_ACCESS,  // read/write permission
                   0,
                   0,
                   BUF_SIZE);
    
       if (pBuf == NULL)
       {
          _tprintf(TEXT("Could not map view of file (%d).\n"),
                 GetLastError());
    
          CloseHandle(hMapFile);
    
          return 1;
       }
    
       MessageBox(NULL, pBuf, TEXT("Process2"), MB_OK);
    
       UnmapViewOfFile(pBuf);
    
       CloseHandle(hMapFile);
    
       return 0;
    }
    
    

  • Lifetime Qt Champion

    Hi and welcome to devnet,

    Did you see that you are not using the same key for both applications ?

    For the Qt application you are using backslashes and for the WinAPI application your are using forward slashes.



  • @SGaist Thank you! I'm fix it. But it's doesn't fix a problem. I'm already testing both variants. In my post it is only typo.


  • Lifetime Qt Champion

    I don't remember if there's a limitation in the characters you can use as key, but i'd start with only ASCII stuff without any special signs.



  • I'm already try to run two copies of Qt application. And it can't transfet data from one thread to another.


  • Lifetime Qt Champion

    What exact error are you getting ?



  • @SGaist I'm changed value of key to simple ASCII: "example".
    Not effect (((
    May be you have an example? I searching it in Google but only one example in qt.io was found.
    No any other(((



  • Probably off topic, but did you consider using QLocalSocket and WINAPI Named Pipe instead



  • @VRonin Good idea. It's will be my fallback. I need to high speed data transfer (up to 10 MBit/s) and shared memory is a faster method of IPC. It's most suitable for my application.



  • Disclaimer

    what follows is just speculation, not advice.


    The problem with shared memory, as I understand it, is that is no way to signal the reader application that new data is available to consume.

    10 MBit/s is not a lot, named pipe should be able to manage it without a problem, in fact, a TCP socket connected to localhost should also be able to handle that transfer rate without a sweat. Both their typical transfer rates are in the multiple Gbit/sec


  • Lifetime Qt Champion

    Check the detailed documentation of QSharedMemory and the setNativeKey. They explain how to achieve communication with non Qt application.



  • @SGaist When I run two copies of Ot application and write some data to shared memory from one of them and the next trying read data from another I have problem: sharedMemory.isAttached() == FALSE for shared memory with same keys.


  • Moderators

    @MR.Smith Didn't you say before that it is working when using two Qt apps and doesn't work if one app is not a Qt app?



  • @VRonin Thank you for recommendation. I will try to use named pipe in my application. It's also good solution for my application.



  • @jsulm Yes, it's true. I can transfer data from one Qt application to another copy of this Qt application, but I can't transfer data from Qt application to WinAPI application.


  • Moderators

    @MR.Smith @SGaist pointed out what you should try



  • I got successfully transfer data via named pipes. It's good solution and I will use it, not shared memory.
    Thank you every one for your help and recommendations.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.