Bug in Win32file WaitCommEvent ???
Dilton McGowan II
diltonm at pacbell.net
Fri Nov 22 13:15:32 EST 2002
"Grant Edwards" <grante at visi.com> wrote in message
news:3ddaa58d$0$4459$a1866201 at newsreader.visi.com...
> I'm trying to figure out how WaitCommEvent() works in Python,
> and it looks like there's a problem when it's used in
> overlapped mode.
>
> My understanding is that (in C) you:
>
> 1) Call WaitCommEvent() and give it three parameters:
> * File handle
> * a pointer to where the output mask value is to be stored
> * a pointer to an overlapped struct
>
> 2) WaitCommEvent() returns immediately.
>
> 3) Call one of the WaitXXX() functions to wait on the event in
> the overloapped struct.
>
> 4) When the event is triggered WaitXXX() returns. Check the
> value stored via the output mask pointer passed in 1)
> above.
>
> [I've gleaned most of this from
> http://msdn.microsoft.com/library/en-us/devio/base/waitcommevent.asp]
>
>
> What I can't figure out: How is this supposed to work in Python?
>
> 1 /* File : win32file.i */
> [...]
> 2089 static PyObject *MyWaitCommEvent(PyObject *self, PyObject *args)
> 2090 {
> 2091 PyObject *obHandle, *obOverlapped = Py_None;
> 2092 if (!PyArg_ParseTuple(args, "O|O",
> 2093 &obHandle, // @pyparm <o PyHANDLE>|handle||The handle
to the communications device.
> 2094 &obOverlapped))// @pyparm <o
PyOVERLAPPED>|overlapped||This structure is required if hFile was opened
with FILE_FLAG_OVERLAPPED.
> 2095 // <nl>If hFile was opened with FILE_FLAG_OVERLAPPED,
the lpOverlapped parameter must not be NULL. It must point to a valid
OVERLAPPED structure. If hFile was opened with FILE_FLAG_OVERLAPPED and
lpOverlapped is NULL, the function can incorrectly report that the operation
is complete.
> 2096 // <nl>If hFile was opened with FILE_FLAG_OVERLAPPED
and lpOverlapped is not NULL, WaitCommEvent is performed as an overlapped
operation. In this case, the OVERLAPPED structure must contain a handle to a
manual-reset event object (created by using the CreateEvent function).
> 2097 // <nl>If hFile was not opened with
FILE_FLAG_OVERLAPPED, WaitCommEvent does not return until one of the
specified events or an error occurs.
> 2098 return NULL;
> 2099 HANDLE handle;
> 2100 if (!PyWinObject_AsHANDLE(obHandle, &handle, FALSE))
> 2101 return NULL;
> 2102 OVERLAPPED *poverlapped;
> 2103 if (!PyWinObject_AsOVERLAPPED(obOverlapped, &poverlapped,
TRUE))
> 2104 return NULL;
> 2105 DWORD mask;
> 2106 BOOL ok;
> 2107 Py_BEGIN_ALLOW_THREADS
> 2108 ok = WaitCommEvent(handle, &mask, poverlapped);
> 2109 Py_END_ALLOW_THREADS
> 2110 DWORD rc = ok ? 0 : GetLastError();
> 2111 if (rc!=0 && rc != ERROR_IO_PENDING)
> 2112 return PyWin_SetAPIError("WaitCommError", rc);
> 2113 return Py_BuildValue("ll", rc, mask);
> 2114 }
>
> I've been looking at the sources above, and the output mask
> pointer passed in 1) points to a _local_ DWORD variable [lines
> 2105, 2108]. Right?
>
> When used in overlapped mode, WaitCommEvent returns before the
> event has happened (and therefore before the output mask value
> has been written). What happens when the event actually occurs
> [between 3) and 4) above] and Win32 writes the output mask
> value? The mask pointer which Win32 has stashed away from the
> call at 1) is no longer valid. I think. Maybe.
>
> How _do_ you get the output mask value in overlapped mode in
> Python?
>
> In C, you do it by passing a mask pointer that points to a
> variable whose lifetime extends past the point in time when the
> event actually happens and the WaitXXX() call returns [and then
> you check the output mask value].
>
> Disclaimer: I'm a Unix guy and find the Win32 stuff to be
> overly complex and baroque. Perhaps I haven't
> understood the MSDN docs and the example C code
> I've seen. If so, I'd be eternally grateful if you
> could point me to decent docs for the Win32 serial
> port API.
>
> --
> Grant Edwards grante Yow! Now KEN and
BARBIE
> at are PERMANENTLY
ADDICTED to
> visi.com MIND-ALTERING DRUGS...
This is from a C++ port read method I wrote some time back. It works for
reading characters.
--------begin---------------
BYTE Byte;
DWORD dwCommModemStatus,
dwBytesTransferred;
// Specify a set of events to be monitored for the port.
//SetCommMask (m_hPort, EV_RXCHAR | EV_CTS | EV_DSR | EV_RLSD | EV_RING);
SetCommMask(m_hPort, EV_RXCHAR);
#ifdef _DEBUG
cout << "\nAbout to wait for comm event" << endl;
#endif
// Wait for an event to occur for the port.
WaitCommEvent(m_hPort, &dwCommModemStatus, NULL);
// WaitCommEvent(m_hPort, &dwCommModemStatus, &m_overlapped);
#ifdef _DEBUG
cout << "\nAfter wait for comm event " << endl;
#endif
// Re-specify the set of events to be monitored for the port.
//SetCommMask (m_hPort, EV_RXCHAR | EV_CTS | EV_DSR | EV_RING);
SetCommMask(m_hPort, EV_RXCHAR);
if (dwCommModemStatus & EV_RXCHAR)
{
#ifdef _DEBUG
cout << "\nIts a receive char" << endl;
#endif
// Loop waiting for the data.
int loop = 0, ret = 0;
do
{
// Read the data from the serial port.
ret = ReadFile(m_hPort, &Byte, 1, &dwBytesTransferred, 0);
//ret = read((int) m_hPort, (void*) &Byte, 1);
// Capture the data read.
if (dwBytesTransferred == 1)
byteArr[loop] = Byte;
loop += 1;
if(loop > MAX_RECV_BUF)
{
#ifdef _DEBUG
cerr << "Serial::PortRead() Exceeded buffer size." << endl;
char msg[512];
memset(msg, '\0', sizeof(msg));
sprintf(msg, "Serial::PortRead() Exceeded buffer size.");
AddToMessageLog(msg);
#endif
return PORT_READ_ERROR;
}
} while (ret != 0 && dwBytesTransferred == 1);
// Read the data from the serial port once more
// to be sure no characters are left.
ret = ReadFile(m_hPort, &Byte, 1, &dwBytesTransferred, 0);
}
return 0;
-----end-------------------
More information about the Python-list
mailing list