Search code examples
c++pointersinterprocess

shared C++ object through memory


I have a quick question for those familiar with inter-process communication.

Situation

  • I have a program (program A) which I can add some code to, but very limited. This is the main program that generate a lot of data.
  • The way the data is formulated is limited, so I would like to create a second program (program B) and hence need to get data from A to B. And even sometimes cause A to run some functions with no return value.
  • I am aware of Named pipes, however I feel they might be bulky? - not sure though - I have for instance the following concerns (may be unfounded):
    1. data flow => convert to binary -> place data in memory -> server Read -> convert to string -> through probably a switch statement determine what is requested -> get what is requested -> convert to binary -> place in memory -> read by client and convert to string / some acceptable format.
    2. It has to use basically switch statements on both sides and if you want a different format of info other than string, you will need to take this into consideration
    3. one message might have to wait for another to complete, so it might be slower during a lot of calls to it at the same time? - not sure though
  • Other inter process communication methods probably has the same problem.
  • Better solution I think would be to create an "object" - class. And share the object memory address between programs, thereby theoretically "merging" the A and B then:

    1. There is no problem with encode and decode issues etc
    2. Data is simply requested / invoked through calling a function.
    3. The function return the proper type and no need to establish what the correct type is (i.e. bool / int / string / double etc)

    I understand that this also has several problems, i.e. if object gets removed from memory location by main / another program accessing it.

Question

  • What is the best way to solve this problems:
  • Is there an invoke option in C++ that will allow me to write and read from a memory address? at the moment:
    1. I can access same object between A and B, but I can't write / read as that will throw an exception. So basically can I through simple invoke perhaps read / write to this object?
    2. I am aware of WriteProcessMemory function - but this is not what I want - i.e. I don't necessarily want to change memory values, merely access data / invoke actions from B that A will perform.
  • Is there a simple and easy way of doing this? I am aware of something called boost, but don't know anything about it - is this my best option? -> i.e. should I investigate this as my best solution?

Thank you in advance for any advise on this issue.


Solution

  • Boost.Interprocess had many ways to share data between processes, one of which is shared_memory

    example taken from boost, where a program acts as server or client for the same memory object (depending on whether an argument is given or not)

    include <boost/interprocess/shared_memory_object.hpp>
    #include <boost/interprocess/mapped_region.hpp>
    #include <cstring>
    #include <cstdlib>
    #include <string>
    
    int main(int argc, char *argv[])
    {
       using namespace boost::interprocess;
    
       if(argc == 1){  //Parent process
          //Remove shared memory on construction and destruction
          struct shm_remove
          {
             shm_remove() { shared_memory_object::remove("MySharedMemory"); }
             ~shm_remove(){ shared_memory_object::remove("MySharedMemory"); }
          } remover;
    
          //Create a shared memory object.
          shared_memory_object shm (create_only, "MySharedMemory", read_write);
    
          //Set size
          shm.truncate(1000);
    
          //Map the whole shared memory in this process
          mapped_region region(shm, read_write);
    
          //Write all the memory to 1
          std::memset(region.get_address(), 1, region.get_size());
    
          //Launch child process
          std::string s(argv[0]); s += " child ";
          if(0 != std::system(s.c_str()))
             return 1;
       }
       else{
          //Open already created shared memory object.
          shared_memory_object shm (open_only, "MySharedMemory", read_only);
    
          //Map the whole shared memory in this process
          mapped_region region(shm, read_only);
    
          //Check that memory was initialized to 1
          char *mem = static_cast<char*>(region.get_address());
          for(std::size_t i = 0; i < region.get_size(); ++i)
             if(*mem++ != 1)
                return 1;   //Error checking memory
       }
       return 0;
    }