Я думаю, у вас есть пара вопросов:
Вы передаете целое число в качестве указателя (ваш компилятор должен предупредить об этом или предпочтительно отказаться от компиляции кода):
result = write_port (outPortHandle, 128);
Сравните это с определением write_port:
int write_port (HANDLE hComm, BYTE * lpBuf) {
Вышеуказанные утверждения не совпадают. Затем вы передаете указатель на указатель lpBuf в функцию WriteFileEx, беря адрес BYTE * -> "& lpBuf". Это не приведет к тому, что, по вашему мнению, будет.
Даже если вы исправите это, у вас все равно будут потенциальные проблемы со временем жизни, когда запись будет успешно поставлена в очередь, но не будет завершена в течение 50 мс времени ожидания.
При использовании перекрывающегося ввода-вывода необходимо убедиться, что буфер чтения / записи и перекрывающаяся структура остаются действительными до тех пор, пока ввод-вывод не будет завершен, отменен или соответствующее устройство не будет закрыто. В приведенном выше коде вы используете указатель на структуру OVERLAPPED, которая находится в стеке при вызове WriteFileEx. Если WriteFileEx не завершится в течение 50 мс, ожидающий ввод-вывод будет иметь ссылку на несуществующую структуру OVERLAPPED, и у вас (надеюсь) будет нарушение доступа (или, что еще хуже, незаметно поврежденные данные стека где-то в вашем приложении).
Канонический способ решения этих проблем времени жизни (если производительность не является большой проблемой) заключается в использовании пользовательской структуры, которая включает в себя структуру OVERLAPPED и некоторое хранилище для данных для чтения / записи. Выделите структуру при публикации записи и освободите структуру из процедуры завершения ввода-вывода. Передайте адрес включенной структуры OVERLAPPED в WriteFileEx и используйте, например, offsetof для получения адреса пользовательской структуры из адреса OVERLAPPED в процедуре завершения.
Также обратите внимание, что WriteFileEx фактически не использует член hEvent, IIRC.
РЕДАКТИРОВАТЬ: Добавлен пример кода, обратите внимание:
- На самом деле я не пытался скомпилировать код, возможны опечатки или другие проблемы с кодом.
- Это не самый эффективный способ отправки данных (выделение / освобождение блока памяти для каждого отправляемого байта). Это должно быть легко улучшить, хотя.
#include <stddef.h>
#include <assert.h>
#include <windows.h>
// ...
typedef struct _MYOVERLAPPED
{
OVERLAPPED ol;
BYTE buffer;
} MYOVERLAPPED, *LPMYOVERLAPPED;
// ...
static void CALLBACK write_compl(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped)
{
if (NULL == lpOverlapped)
{
assert(!"Should never happen");
return;
}
LPBYTE pOlAsBytes = (LPBYTE)lpOverlapped;
LPBYTE pMyOlAsBytes = pOlAsBytes - offsetof(MYOVERLAPPED, ol);
LPMYOVERLAPPED pMyOl = (LPMYOVERLAPPED)pOlAsBytes;
if ((ERROR_SUCCESS == dwErrorCode) &&
(sizeof(BYTE) == dwNumberOfBytesTransfered))
{
printf("written %uc\n", pMyOl->buffer);
}
else
{
// handle error
}
free(pMyOl);
}
int write_port(HANDLE hComm, BYTE byte) {
LPMYOVERLAPPED pMyOl = (LPMYOVERLAPPED)malloc(sizeof(MYOVERLAPPED));
ZeroMemory(pMyOl, sizeof(MYOVERLAPPED));
pMyOl->buffer = byte;
// Issue write.
if (!WriteFileEx(hComm, &pMyOl->buffer, sizeof(BYTE), pMyOl, &write_compl )) {
if (GetLastError() != ERROR_IO_PENDING) {
// WriteFile failed, but isn't delayed. Report error and abort.
free(pMyOl);
printf("last error: %ld",GetLastError());
return 0; //failed, return false;
}
else {
return -1; //pending
}
}
else {
free(pMyOl);
return 1; //finished
}
}