Search code examples
c++serializationcastingnamed-pipesfifo

C++ : Send an object through a named pipe


I try to send an object through a named pipe, between two process, in C++ with ifstream and ofstream. I have read and try so many things but my research has led to nothing.

I block during the serialization of my object. When I try to cast and send to my named pipe, I can not recover my object to his normale state.

I try something with this code but the object is not full after its passage in the named pipe :

#include <string.h>
#include <iostream>
#include <unistd.h>
#include <fstream>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>

class Obj {
public:
    std::string text1;
    std::string text2;
};

int main() {

    mkfifo("fifo", 0666);

    if (fork() == 0) //Receiving Side
    {

        std::ifstream fifo("fifo", std::ofstream::binary);

        //Re-make the object
        Obj *tmp = new Obj();
        char *b = new char[sizeof(*tmp)];

        //Receive from named pipe
        fifo >> b;

        //Recover the object
        memcpy(&*tmp, b, sizeof(*tmp));

        //Display object content
        std::cout << tmp->text1 << std::endl << tmp->text2 << std::endl;

        //!\ Output = "Some \n" /!\\

        fifo.close();
        delete tmp;
        delete[] b;
    }
    else //Sending Side
    {
        std::ofstream fifo("fifo", std::ofstream::binary);

        //Create the object
        Obj *struct_data = new Obj();
        struct_data->text1 = "Some text";
        struct_data->text2 = "Some text";

        char *b = new char[sizeof(*struct_data)];

        //Serialize the object
        memcpy((void *)b, &*struct_data, sizeof(*struct_data));

        //Send to named pipe
        fifo << b;

        fifo.close();
        wait(NULL);
        delete[] b;
    }

    //delete struct_data;
    return (0);
}

Does someone could give me a tip or en example ?

Thanks ! :)


Solution

  • You will need to serialize your object properly. Something like this (just did one member, the rest will be left as an excercise to the reader):

    #include <iostream>
    #include <fstream>
    #include <cstring>
    #include <sys/types.h>
    #include <sys/stat.h>
    
    class Obj
    {
      public:
        std::string text1;
        std::string text2;
    
      friend std::ostream& operator<<(std::ostream &os, const Obj& o);
      friend std::istream& operator>>(std::istream &os, Obj& o);
    };
    
    std::ostream& operator<<(std::ostream &os, const Obj& o)
    {
      os << o.text1.length();
      os << o.text1;
      return os;
    }
    
    std::istream& operator>>(std::istream &is, Obj& o)
    {
      size_t length;
      is >> length;
      char* tmp = new char[length];
      is.get(tmp, length+1); 
      o.text1 = tmp;
      delete[] tmp;
      return is;
    }
    
    static const char* myfifo = "myfifo";
    
    int main(int argc, char *argv[])
    {
      mkfifo(myfifo, 0666);
    
      if (argc > 1)
      {       
        std::ifstream infifo(myfifo, std::ifstream::binary);
    
        Obj *tmp = new Obj();
    
        infifo >> *tmp; 
        infifo.close();
    
        std::cout << "Done reading : [" << tmp->text1 << "]" << std::endl;
      }
      else
      {
        std::ofstream outfifo(myfifo, std::ofstream::binary);
    
        Obj *struct_data = new Obj();
        struct_data->text1 = "Some text1";
        struct_data->text2 = "Some text2";
    
        outfifo << *struct_data;
      }
      return 0;
    }
    

    For more on serialization see https://stackoverflow.com/a/26337239/2742863