Это моя структура PER_IO_CONTEXT (я сохранил их в односвязном списке):
typedef struct _PER_IO_CONTEXT
{
SLIST_ENTRY ItemEntry;
WSAOVERLAPPED Overlapped;
WSABUF wsabuf;
/* some other data*/
} PER_IO_CONTEXT, *PPER_IO_CONTEXT;
и ниже WSAsend, который использует список для получения структуры WSAOVERLAPPED:
...
PSLIST_HEADER pListHead;
...
PSLIST_ENTRY pListEntry = InterlockedPopEntrySList(pListHead);
PPER_IO_CONTEXT ovl = (PPER_IO_CONTEXT)pListEntry;
WSASend(pTmp1->Socket,..., &(ovl->Overlapped), NULL);
и последняя часть, когда GQCS получает уведомление:
LPWSAOVERLAPPED lpOverlapped = NULL;
PPER_IO_CONTEXT lpIOContext = NULL;
....
GetQueuedCompletionStatus(..... (LPOVERLAPPED *)&lpOverlapped, INFINITE);
lpIOContext = (PPER_IO_CONTEXT)lpOverlapped;
lpIOContext->wsabuf // this fail
Как вы можете увидеть следующий актерский состав lpIOContext = (PPER_IO_CONTEXT) lpOverlapped не работает, потому что WSAsend был снабжен wsaoverlapped — вторым членом структуры PER_IO_CONTEXT, поэтому разыменования, такие как lpIOContext->, не могут использоваться в этом случае.
Есть ли способ справиться с этой ситуацией?
Чтобы получить адрес соответствующей структуры PER_IO_CONTEXT, вы можете использовать это:
lpIOContext = CONTAINING_RECORD(lpOverlapped, PER_IO_CONTEXT, Overlapped);
CONTAINING_RECORD — это макрос, определенный в VC\crt\src\collections.h
в таком случае:
#define CONTAINING_RECORD(address, type, field) \
((type *)((char *)(address) - (ULONG_PTR)(&((type *)0)->field)))
Дополнительная информация: http://msdn.microsoft.com/en-us/library/windows/hardware/ff542043%28v=vs.85%29.aspx
Я не уверен, есть ли поддерживаемый механизм для преобразования указателя на член структуры в указатель на структуру. Вы мог бросить все на BYTE *
и сделайте арифметику, которая будет работать на практике, но в зависимости от ваших потребностей, может быть, лучше провести реорганизацию, чтобы избежать необходимости:
typedef struct _PER_IO_CONTEXT
{
WSAOVERLAPPED Overlapped;
WSABUF wsabuf;
/* some other data*/
} PER_IO_CONTEXT, *PPER_IO_CONTEXT;
typedef struct _PER_IO_CONTEXT_LIST_ITEM
{
SLIST_ENTRY ItemEntry;
PER_IO_CONTEXT Item;
} PER_IO_CONTEXT_LIST_ITEM, *PPER_IO_CONTEXT_LIST_ITEM;