这是我的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,使用该列表获取WSOAVERLAPPED结构:
...
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->在这种情况下不能使用。
有办法处理这种情况吗?
答案 0 :(得分:2)
要获取相应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
答案 1 :(得分:1)
我不确定是否有支持的机制将指向结构成员的指针转换为指向结构的指针。您可以将所有内容投射到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;