I've finally mannaged to pull off a set of wrappers for using the raw windows iocp api using ctypes, namely wrappers for GetQueuedCompletionStatus, WSARecv, WSASend, AcceptEx, ConnectEx, TransmitFile and the whatever structs and utility calls they need.
Writing the wrappers wasn't that hard - but if you aren't careful with ctypes you are in a world of gruesome crashes and at least 2 wasted evenings (read nights) debugging why the hell some random allocation fails. Well, for a fact, I still have no idea to why do I own those to wasted nights but thank god it doesn't crash on my unittests anymore - I think I could have figured out why some missing object cleanup resulted in weird crashes if I knew some ctypes internals but eh, I don't :(
Take a look at the evil code here and here, and punish me for doing such an evil thing with ctypes *malefic laugh* =]
Here's a gem:
# signature: BOOL = SOCKET hSocket, HANDLE hFile, DWORD nNumberOfBytesToWrite, DWORD nNumberOfBytesPerSend, LPOVERLAPPED lpOverlapped,LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers, DWORD dwFlags
TransmitFileType = WINFUNCTYPE(BOOL, SOCKET, HANDLE, DWORD, DWORD, POINTER(OVERLAPPED), POINTER(TRANSMIT_FILE_BUFFERS), DWORD)
def _GetTransmitFilePtr(given_socket=None):
from socket import socket
bogus_sock = given_socket or socket()
bogus_bytes = DWORD()
TransmitFile = TransmitFileType(0)
ret = WSAIoctl(
bogus_sock.fileno(), SIO_GET_EXTENSION_FUNCTION_POINTER, byref(WSAID_TRANSMITFILE), sizeof(WSAID_TRANSMITFILE),
byref(TransmitFile), sizeof(TransmitFile), byref(bogus_bytes), None, None
)
return TransmitFile
TransmitFile = _GetTransmitFilePtr()
So far the new proactor works pretty nice in cogen.