1

I found this StackOverflow question:

Create Named Pipe C++ Windows

And created this class:

#pragma once

#define PIPE_FD TEXT("\\\\.\\pipe\\somepipe")

#define BUFFER_SIZE 1024

// CPipe Class
class CPipe
{

private:

    //
    // Variables
    //

    HANDLE hPipe;
    char buffer[BUFFER_SIZE];
    DWORD dwRead;
    DWORD dwWritten;

public:

    bool CreatePipe()
    {
        hPipe = CreateNamedPipe(PIPE_FD, PIPE_ACCESS_DUPLEX | PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, PIPE_WAIT, 1, BUFFER_SIZE * 16, BUFFER_SIZE * 16, NMPWAIT_USE_DEFAULT_WAIT, NULL);

        return (hPipe == NULL) ? false : true;
    }

    bool CreatePipeFile()
    {
        hPipe = CreateFile(PIPE_FD, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);

        return (hPipe == NULL) ? false : true;
    }

    void Destroy()
    {
        DisconnectNamedPipe(hPipe);
    }

    bool IsPipe()
    {
        return (hPipe == NULL) ? false : true;
    }

    bool IsConnected()
    {
        return (ConnectNamedPipe(hPipe, NULL) != FALSE) ? true : false;
    }

    void Read()
    {
        while (ReadFile(hPipe, buffer, sizeof(buffer), &dwRead, NULL) != FALSE)
        {
            /* do something with data in buffer */
            printf("%s", buffer);
        }
    }

    void Write()
    {
        WriteFile(hPipe, "Hello Pipe\n", 12, &dwWritten, NULL);

        CloseHandle(hPipe);
    }
};

extern CPipe gPipe;

Main Process:

    gPipe.CreatePipe();
    while (gPipe.IsPipe())
    {
        if (gPipe.IsConnected())
        {
            gPipe.Read();
        }

        gPipe.Destroy();
    }

Remote:

    gPipe.CreatePipeFile();
    if (gPipe.IsPipe())
    {
        gPipe.Write();
    }

Which works great. I can send "Hello Pipe\n" between two applications. However, I am trying to modify it to send data structures rather than strings.

For example, this structure:

struct Test_t
{
    int x;
    int y;
    float J[3];
    bool Yes;
};

That way, the client can send the structure over the pipe, and the server can read the structure off the pipe and update local server structs accordingly.

I have tried:

reinterpret_cast<char*>(&test);

But I haven't been able to get it to work. Any ideas?

Any help is appreciated.

Community
  • 1
  • 1
Pat
  • 649
  • 1
  • 8
  • 24
  • Just to warn you, if you change that struct to non-POD, your method of just passing the entire struct will not work. – PaulMcKenzie Mar 09 '15 at 00:28

1 Answers1

1

The reinterpret cast should probably look like this:

reinterpret_cast<void*>(&test);

You also need to make sure you get the amount of data to transfer right (sizeof is your friend here).

Note that sending structs like that can get risky.

  • The objects sent need to be plain old data objects or they will not serialize properly. See What are POD types in C++? for more information about plain old data. Pointer members, virtual functions etc. will not work.
  • If the two processes talking to each other have different ideas about structure packing things will come out wrong on the other side. As long as you have full control over the build environment this should be fine, but when things starts breaking you can get some really nasty bugs to fix.

Unless you have extreme performance considerations you should look into some more organized way of serializing the data you send over the pipe such as google protocol buffers or boost::serialize that will make sure the wire format is a little bit less fragile. protocol buffers (and many other technologies) have the advantage of not being c++ specific so you can talk between processes created in different programming languages.

Community
  • 1
  • 1
Laserallan
  • 11,072
  • 10
  • 46
  • 67