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