Reputation: 1258
I have a program written in Python that I need to contact from a C++ Program. I'm creating the Pipe Server on the C++ program with the client being in Python. I can't wrap my head around how to properly read/write between the 2 programs as each time I try a different behavior occurs. Note that I want the pipe to remain open for multiple reads/writes into the future.
Server (C++)
#include <windows.h>
#include <iostream>
using namespace std;
#define FGPIPE TEXT("\\\\.\\pipe\\FGChroma")
int main()
{
HANDLE hPipe;
DWORD dwWritten;
DWORD MAX_BUF_SIZE = 8;
hPipe = CreateNamedPipe(FGPIPE,
PIPE_ACCESS_OUTBOUND,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
2,
MAX_BUF_SIZE*16,
0,
NMPWAIT_USE_DEFAULT_WAIT,
NULL
);
cout<<"Pipe? "<<hPipe<<endl;
cout<<"Awaiting Connection"<<endl;
cout<<ConnectNamedPipe(hPipe, NULL)<<endl;
cout<<"Connected"<<endl;
WriteFile(hPipe, "MSG1\n", 5, &dwWritten, NULL);
WriteFile(hPipe, "MSG2\n", 5, &dwWritten, NULL);
FlushFileBuffers(hPipe);
///Need to Wait for read here
cout<<"Disconnecting"<<endl;
DisconnectNamedPipe(hPipe);
}
Client (Python)
f = open(r"\\.\\pipe\\FGChroma", 'r', 0)
while True:
value = f.read()
print(value)
When I attempt to do the f.read()
in Python, I get an error OSError 22 Invalid Argument, which is fair since I've disconnected the pipe. However if I don't disconnect the pipe then the Python code never finishes reading and keeps waiting until the pipe is closed or disconnected. I feel like the solution is simple and I'm just missing something tiny that's going over my head. I read the Documentation for named pipes and the Win APIs, I also tried win32py and other alternatives and I face the same issue; I don't understand how to keep a connection alive between the 2 instances and allow for reading without having to disconnect, or to wait for reading.
Upvotes: 0
Views: 905
Reputation: 1258
Based on ElderBug's answer above, here's a working solution that doesn't use buffers, but instead uses an end of line terminator. You may need to adjust your code accordingly.
def read_line(file_handle):
EOF = False
data = ""
while True:
try:
c = file_handle.read(1).decode("utf-8")
except OSError: # EOF
EOF = True
break
if c == '\n':
break
if not c:
EOF = True
break
data += c
return data, EOF
print("Connecting to Pipe")
while True:
try:
f = open(r"\\.\\pipe\\FGChroma", 'rb', 0)
break
except FileNotFoundError:
continue
print("Connected")
print("Reading Data")
while True:
data, EOF = read_line(f)
if EOF: break
print(data)
You may need to switch read mode from 'rb'
to 'r'
as well. Use b
only for Binary mode, but then you'll have to enable buffering by setting buffer mode to 1
from 0
.
Upvotes: 0
Reputation: 6145
I think there is a problem with Python f.read()
and Windows pipes. Maybe I missed something but it looks like there is no EOF when you read a pipe like you do, and python read()
will read past the end and error, even though it read everything correctly before.
To work around this, you can use a buffered pipe (open(r"pipe", 'r')
) and then either read characters one by one (f.read(1)
) until you have an error, or use os.read(f.fileno(), 1024)
, which is lower level and works in this case.
Upvotes: 1
Reputation: 1959
you can have a look here Python and Windows Named Pipes
thought on windows open a file by more than one program is not like on unix. If you can't avoid it use win32pipe but that makes your code not plattform indipendent
Upvotes: 0