WSAAsyncSelect
関数シグネチャ
// WS2_32.dll
#include <windows.h>
INT WSAAsyncSelect(
SOCKET s,
HWND hWnd,
DWORD wMsg,
INT lEvent
);パラメーター
| 名前 | 型 | 方向 | 説明 |
|---|---|---|---|
| s | SOCKET | in | イベント通知を必要とするソケットを識別する記述子。 |
| hWnd | HWND | in | ネットワークイベントが発生したときにメッセージを受信するウィンドウを識別するハンドル。 |
| wMsg | DWORD | in | ネットワークイベントが発生したときに受信するメッセージ。 |
| lEvent | INT | in | アプリケーションが関心を持つネットワークイベントの組み合わせを指定するビットマスク。 |
戻り値の型: INT
公式ドキュメント
WSAAsyncSelect 関数 (winsock.h) は、ソケットに対するネットワークイベントを Windows メッセージベースで通知するよう要求します。
戻り値
WSAAsyncSelect 関数が成功し、ネットワークイベントセットへの関心の宣言が成功した場合、戻り値は 0 です。それ以外の場合は SOCKET_ERROR が返され、 WSAGetLastError を呼び出すことで特定のエラー番号を取得できます。
| エラーコード | 意味 |
|---|---|
| この関数を使用する前に、 WSAStartup の呼び出しが成功している必要があります。 | |
| ネットワークサブシステムが失敗しました。 | |
| 指定されたパラメーターのいずれかが無効でした。たとえば、ウィンドウハンドルが既存のウィンドウを参照していない、または指定されたソケットが無効な状態にある場合などです。 | |
| ブロッキング動作の Windows Sockets 1.1 呼び出しが進行中であるか、サービスプロバイダーがコールバック関数を処理中です。 | |
| 記述子がソケットではありません。 |
アプリケーションウィンドウがメッセージを受信したときに、追加のエラーコードが設定される場合があります。このエラーコードは、WSAGETSELECTERROR マクロを使用して応答メッセージの lParam から抽出されます。各ネットワークイベントで発生しうるエラーコードを次の表に示します。
イベント: FD_CONNECT
| エラーコード | 意味 |
|---|---|
| WSAEAFNOSUPPORT | 指定されたファミリのアドレスは、このソケットでは使用できません。 |
| WSAECONNREFUSED | 接続の試行が拒否されました。 |
| WSAENETUNREACH | 現時点で、このホストからネットワークに到達できません。 |
| WSAEFAULT | namelen パラメーターが無効です。 |
| WSAEINVAL | ソケットは既にアドレスにバインドされています。 |
| WSAEISCONN | ソケットは既に接続されています。 |
| WSAEMFILE | 使用可能なファイル記述子がこれ以上ありません。 |
| WSAENOBUFS | 使用可能なバッファー領域がありません。ソケットを接続できません。 |
| WSAENOTCONN | ソケットが接続されていません。 |
| WSAETIMEDOUT | 接続を確立できずに接続の試行がタイムアウトしました。 |
イベント: FD_CLOSE
| エラーコード | 意味 |
|---|---|
| WSAENETDOWN | ネットワークサブシステムが失敗しました。 |
| WSAECONNRESET | 接続がリモート側によってリセットされました。 |
| WSAECONNABORTED | タイムアウトまたはその他の障害により接続が終了しました。 |
| エラーコード | 意味 |
|---|---|
| WSAENETDOWN | ネットワークサブシステムが失敗しました。 |
イベント: FD_ROUTING_INTERFACE_CHANGE
| エラーコード | 意味 |
|---|---|
| WSAENETUNREACH | 指定された宛先に到達できなくなりました。 |
| WSAENETDOWN | ネットワークサブシステムが失敗しました。 |
解説(Remarks)
WSAAsyncSelect 関数は、lEvent パラメーターで指定されたネットワークイベントを WS2_32.DLL が検出したときに、ウィンドウ hWnd にメッセージを送信するよう要求するために使用されます。送信すべきメッセージは wMsg パラメーターで指定します。通知が必要なソケットは s パラメーターで識別します。
WSAAsyncSelect 関数は、lEvent の値にかかわらず、ソケット s を自動的に非ブロッキングモードに設定します。ソケット s をブロッキングモードに戻すには、まず lEvent を 0 に設定して WSAAsyncSelect を呼び出し、ソケット s に関連付けられたイベントレコードをクリアする必要があります。その後、ioctlsocket または WSAIoctl を呼び出して、ソケットをブロッキングモードに戻すことができます。非ブロッキングソケットをブロッキングモードに戻す方法の詳細については、ioctlsocket 関数と WSAIoctl 関数を参照してください。
lEvent パラメーターは、次の表に示す値のいずれかをビットごとの OR 演算子で組み合わせて構成します。
| 値 | 意味 |
|---|---|
| FD_READ | 読み取り準備完了の通知を受信するために設定します。 |
| FD_WRITE | 書き込み準備完了の通知を受信します。 |
| FD_OOB | OOB データの到着の通知を受信します。 |
| FD_ACCEPT | 着信接続の通知を受信します。 |
| FD_CONNECT | 接続またはマルチポイント結合操作の完了の通知を受信します。 |
| FD_CLOSE | ソケットのクローズの通知を受信します。 |
| FD_QOS | ソケットの Quality of Service (QoS) の変更の通知を受信します。 |
| FD_GROUP_QOS | ソケットグループの Quality of Service (QoS) の変更の通知を受信します (ソケットグループでの将来の使用のために予約)。予約済み。 |
| FD_ROUTING_INTERFACE_CHANGE | 指定された宛先に対するルーティングインターフェイスの変更の通知を受信します。 |
| FD_ADDRESS_LIST_CHANGE | ソケットのプロトコルファミリのローカルアドレスリストの変更の通知を受信します。 |
ソケットに対して WSAAsyncSelect を発行すると、同じソケットに対する以前の WSAAsyncSelect または WSAEventSelect がキャンセルされます。たとえば、読み取りと書き込みの両方の通知を受け取るには、アプリケーションは次のように FD_READ と FD_WRITE の両方を指定して WSAAsyncSelect を呼び出す必要があります。
rc = WSAAsyncSelect(s, hWnd, wMsg, FD_READ|FD_WRITE);
イベントごとに異なるメッセージを指定することはできません。次のコードは機能しません。2 番目の呼び出しが 1 番目の呼び出しの効果をキャンセルし、メッセージ wMsg2 で報告されるのは FD_WRITE イベントのみとなります。
rc = WSAAsyncSelect(s, hWnd, wMsg1, FD_READ);
rc = WSAAsyncSelect(s, hWnd, wMsg2, FD_WRITE);
すべての通知をキャンセルし、ソケット上のネットワークイベントに関連するメッセージを Windows Sockets がこれ以上送信しないようにするには、lEvent を 0 に設定します。
rc = WSAAsyncSelect(s, hWnd, 0, 0);
この場合、WSAAsyncSelect はソケットに対するイベントメッセージの投稿を即座に無効にしますが、メッセージがアプリケーションのメッセージキュー内で待機している可能性があります。したがって、アプリケーションはキャンセル後であってもネットワークイベントメッセージを受信できるよう準備しておく必要があります。 closesocket でソケットをクローズすると、 WSAAsyncSelect によるメッセージ送信もキャンセルされますが、キュー内のメッセージに関する同じ注意事項が引き続き当てはまります。
accept 関数によって作成されたソケットは、それを受け入れるために使用されたリスニングソケットと同じプロパティを持ちます。その結果、リスニングソケットに設定された WSAAsyncSelect イベントは、受け入れられたソケットにも適用されます。たとえば、リスニングソケットに WSAAsyncSelect イベント FD_ACCEPT、FD_READ、FD_WRITE が設定されている場合、そのリスニングソケットで受け入れられたソケットも、メッセージに使用される同じ wMsg 値で FD_ACCEPT、FD_READ、FD_WRITE イベントを持ちます。異なる wMsg やイベントが必要な場合、アプリケーションは受け入れられたソケットと希望する新しいデータを渡して WSAAsyncSelect を呼び出す必要があります。
指定されたソケット s 上で、指定されたネットワークイベントのいずれかが発生すると、アプリケーションウィンドウ hWnd はメッセージ wMsg を受信します。wParam パラメーターは、ネットワークイベントが発生したソケットを識別します。lParam の下位ワードは発生したネットワークイベントを指定します。lParam の上位ワードにはエラーコードが含まれます。エラーコードは Winsock2.h で定義された任意のエラーになりえます。
#include <windows.h>
#define WSAGETSELECTEVENT(lParam) LOWORD(lParam)
#define WSAGETSELECTERROR(lParam) HIWORD(lParam)
これらのマクロを使用することで、アプリケーションのソースコードの移植性が最大限に高まります。
返される可能性のあるネットワークイベントコードを次の表に示します。
| 値 | 意味 |
|---|---|
| FD_READ | ソケット s が読み取り準備完了です。 |
| FD_WRITE | ソケット s が書き込み準備完了です。 |
| FD_OOB | ソケット s で OOB データの読み取り準備が完了しました。 |
| FD_ACCEPT | ソケット s が新しい着信接続を受け入れる準備が完了しました。 |
| FD_CONNECT | ソケット s 上で開始された接続またはマルチポイント join 操作が完了しました。 |
| FD_CLOSE | ソケット s で識別される接続がクローズされました。 |
| FD_QOS | ソケット s に関連付けられた Quality of Service が変更されました。 |
| FD_GROUP_QOS | 予約済み。s が属するソケットグループに関連付けられた Quality of Service が変更されました (ソケットグループでの将来の使用のために予約)。 |
| FD_ROUTING_INTERFACE_CHANGE | 指定された宛先への送信に使用すべきローカルインターフェイスが変更されました。 |
| FD_ADDRESS_LIST_CHANGE | アプリケーションクライアントがバインドできるソケットプロトコルファミリのアドレスリストが変更されました。 |
WSAAsyncSelect は複数のイベントへの関心を指定して呼び出すことができますが、アプリケーションウィンドウはネットワークイベントごとに 1 つのメッセージを受信します。
select 関数の場合と同様に、 WSAAsyncSelect は、データ転送操作 (send または recv) を即座に成功する見込みで発行できるタイミングを判断するために頻繁に使用されます。とはいえ、堅牢なアプリケーションは、メッセージを受信して Windows Sockets 2 の呼び出しを発行したときに、即座に WSAEWOULDBLOCK が返される可能性に備える必要があります。たとえば、次の一連のイベントが起こりえます。
- ソケット s にデータが到着し、Windows Sockets 2 が WSAAsyncSelect メッセージを投稿します。
- アプリケーションが別のメッセージを処理します。
- 処理中に、アプリケーションが
ioctlsocket(s, FIONREAD...)を発行し、読み取り可能なデータがあることを認識します。 - アプリケーションが
recv(s,...)を発行してデータを読み取ります。 - アプリケーションがループして次のメッセージを処理し、最終的にデータの読み取り準備が完了したことを示す WSAAsyncSelect メッセージに到達します。
- アプリケーションが
recv(s,...)を発行しますが、エラー WSAEWOULDBLOCK で失敗します。
WS2_32.DLL は、特定のネットワークイベントに対するメッセージでアプリケーションを継続的に氾濫させることはありません。特定のイベントの通知をアプリケーションウィンドウに正常に投稿した後は、アプリケーションがそのネットワークイベントの通知を暗黙的に再有効化する関数呼び出しを行うまで、そのネットワークイベントに対するそれ以上のメッセージはアプリケーションウィンドウに投稿されません。
| イベント | 再有効化する関数 |
|---|---|
| FD_READ | recv、 recvfrom、 WSARecv、または WSARecvFrom。 |
| FD_WRITE | send、 sendto、 WSASend、または WSASendTo。 |
| FD_OOB | recv、 recvfrom、 WSARecv、または WSARecvFrom。 |
| FD_ACCEPT | accept または WSAAccept。ただし、エラーコードが WSATRY_AGAIN であり、条件関数が CF_DEFER を返したことを示している場合を除きます。 |
| FD_CONNECT | なし。 |
| FD_CLOSE | なし。 |
| FD_QOS | コマンド SIO_GET_QOS を指定した WSAIoctl。 |
| FD_GROUP_QOS | 予約済み。 コマンド SIO_GET_GROUP_QOS を指定した WSAIoctl (ソケットグループでの将来の使用のために予約)。 |
| FD_ROUTING_INTERFACE_CHANGE | コマンド SIO_ROUTING_INTERFACE_CHANGE を指定した WSAIoctl。 |
| FD_ADDRESS_LIST_CHANGE | コマンド SIO_ADDRESS_LIST_CHANGE を指定した WSAIoctl。 |
再有効化ルーチンへの呼び出しは、たとえ失敗した呼び出しであっても、該当するイベントに対するメッセージ投稿の再有効化につながります。
FD_READ、FD_OOB、FD_ACCEPT イベントの場合、メッセージ投稿はレベルトリガーです。これは、再有効化ルーチンが呼び出され、その呼び出し後も該当する条件が依然として満たされている場合に、 WSAAsyncSelect メッセージがアプリケーションに投稿されることを意味します。これにより、アプリケーションはイベント駆動型となり、一度に到着するデータ量を気にする必要がなくなります。次の順序を考えてみます。
- ネットワークトランスポートスタックがソケット s 上で 100 バイトのデータを受信し、Windows Sockets 2 に FD_READ メッセージを投稿させます。
- アプリケーションが recv( s, buffptr, 50, 0) を発行して 50 バイトを読み取ります。
- 読み取るべきデータがまだ残っているため、別の FD_READ メッセージが投稿されます。
FD_QOS および FD_GROUP_QOS イベントはエッジトリガーと見なされます。Quality of Service の変更が発生したとき、メッセージは正確に 1 回だけ投稿されます。プロバイダーが Quality of Service のさらなる変更を検出するか、アプリケーションがソケットの Quality of Service を再交渉するまで、それ以上のメッセージは送信されません。
FD_ROUTING_INTERFACE_CHANGE メッセージは、SIO_ROUTING_INTERFACE_CHANGE を指定した WSAIoctl で指定された宛先に到達するために使用すべきローカルインターフェイスが、その IOCTL の発行後に変更されたときに投稿されます。
FD_ADDRESS_LIST_CHANGE メッセージは、SIO_ADDRESS_LIST_CHANGE を指定した WSAIoctl の発行後に、アプリケーションがバインドできるアドレスのリストが変更されたときに投稿されます。
アプリケーションが WSAAsyncSelect を呼び出したとき、または再有効化関数が呼び出されたときに何らかのイベントが発生していた場合、必要に応じてメッセージが投稿されます。たとえば、次の順序を考えてみます。
- アプリケーションが listen を呼び出します。
- 接続要求を受信しますが、まだ受け入れられていません。
- アプリケーションが、そのソケットに対して FD_ACCEPT メッセージの受信を必要とすることを指定して WSAAsyncSelect を呼び出します。イベントの永続性により、Windows Sockets 2 は即座に FD_ACCEPT メッセージを投稿します。
FD_WRITE イベントの扱いは少し異なります。FD_WRITE メッセージは、ソケットが connect または WSAConnect で最初に接続されたとき (FD_CONNECT も登録されている場合はその後)、あるいは accept または WSAAccept で受け入れられたとき、そしてその後、送信操作が WSAEWOULDBLOCK で失敗してからバッファー領域が利用可能になったときに投稿されます。したがって、アプリケーションは、最初の FD_WRITE メッセージから、送信が WSAEWOULDBLOCK を返すまでの間、送信が可能であると想定できます。そのような失敗の後、アプリケーションは FD_WRITE メッセージによって再び送信が可能になったことを通知されます。
FD_OOB イベントは、ソケットが OOB データを個別に受信するよう構成されている場合にのみ使用されます。ソケットが OOB データをインラインで受信するよう構成されている場合、OOB (緊急) データは通常のデータとして扱われ、アプリケーションは FD_OOB イベントではなく FD_READ イベントに関心を登録し、それを受信します。アプリケーションは、SO_OOBINLINE オプションに対して setsockopt または getsockopt を使用することで、OOB データの処理方法を設定または検査できます。
FD_CLOSE メッセージのエラーコードは、ソケットのクローズが正常 (graceful) であったか異常 (abortive) であったかを示します。エラーコードが 0 の場合、クローズは正常でした。エラーコードが WSAECONNRESET の場合、ソケットの仮想回線がリセットされました。これは、SOCK_STREAM などのコネクション指向ソケットにのみ適用されます。
FD_CLOSE メッセージは、ソケットに対応する仮想回線のクローズ通知を受信したときに投稿されます。TCP の用語では、これは接続が TIME WAIT 状態または CLOSE WAIT 状態に移行したときに FD_CLOSE が投稿されることを意味します。これは、リモート側が送信側で shutdown を実行したか、 closesocket を実行した結果として発生します。FD_CLOSE は、ソケットからすべてのデータが読み取られた後にのみ投稿されるべきですが、データ損失の可能性を回避するため、アプリケーションは FD_CLOSE を受信した際に残りのデータがないかを確認する必要があります。
アプリケーションが仮想回線のクローズを示す FD_CLOSE メッセージを受信するのは、正常なクローズの場合は受信したすべてのデータが読み取られたときのみであることに注意してください。この状態を示す FD_READ メッセージは受信されません。
FD_QOS または FD_GROUP_QOS メッセージは、それぞれソケット s に関連付けられたフロー仕様、または s が属するソケットグループのフロー仕様内のいずれかのパラメーターが変更されたときに投稿されます。アプリケーションは、ソケット s または s が属するソケットグループの現在の Quality of Service を取得するために、それぞれコマンド SIO_GET_QOS または SIO_GET_GROUP_QOS を指定した WSAIoctl を使用する必要があります。
FD_ROUTING_INTERFACE_CHANGE および FD_ADDRESS_LIST_CHANGE イベントもエッジトリガーと見なされます。アプリケーションが SIO_ROUTING_INTERFACE_CHANGE または SIO_ADDRESS_LIST_CHANGE を指定した WSAIoctl を発行して通知を要求した後、変更が発生したとき、メッセージは正確に 1 回だけ投稿されます。アプリケーションが IOCTL を再発行し、その IOCTL が発行されたために別の変更が検出されるまで、それ以上のメッセージは送信されません。
各非同期通知メッセージのイベントと条件の概要を次に示します。
- FD_READ:
- WSAAsyncSelect が呼び出されたとき、現在受信可能なデータがある場合。
- データが到着したとき、FD_READ がまだ投稿されていない場合。
-
recv または
recvfrom が (MSG_PEEK の有無にかかわらず) 呼び出された後、まだ受信可能なデータがある場合。
注意 setsockopt SO_OOBINLINE が有効な場合、上記の各ケースにおいてデータには通常のデータと OOB データの両方が含まれます。
- FD_WRITE:
- FD_OOB: setsockopt SO_OOBINLINE が無効 (既定) の場合にのみ有効です。
- FD_ACCEPT:
- FD_CONNECT:
- WSAAsyncSelect が呼び出されたとき、現在確立された接続がある場合。
- connect が呼び出された後、接続が確立されたとき。データグラムソケットで典型的なように、 connect が即座に成功する場合も含みます。
- WSAJoinLeaf を呼び出した後、結合操作が完了したとき。
- 非ブロッキングのコネクション指向ソケットで connect、 WSAConnect、または WSAJoinLeaf が呼び出された後。初期操作は WSAEWOULDBLOCK という特定のエラーで返されましたが、ネットワーク操作は続行されました。操作が最終的に成功するかどうかにかかわらず、結果が確定したときに FD_CONNECT が発生します。クライアントはエラーコードを確認して、結果が成功したか失敗したかを判断する必要があります。
- FD_CLOSE: コネクション指向ソケット (例: SOCK_STREAM) でのみ有効です。
- WSAAsyncSelect が呼び出されたとき、ソケット接続がクローズされている場合。
- リモートシステムが正常なクローズを開始した後、現在受信可能なデータがないとき (リモートシステムが正常なクローズを開始したときに受信済みで読み取り待ちのデータがある場合、保留中のすべてのデータが読み取られるまで FD_CLOSE は配信されないことに注意してください)。
- ローカルシステムが shutdown で正常なクローズを開始し、リモートシステムが「データの終わり」通知 (例: TCP FIN) で応答した後、現在受信可能なデータがないとき。
- リモートシステムが接続を終了したとき (例: TCP RST を送信)。このとき lParam には
WSAECONNRESET エラー値が含まれます。
注意 FD_CLOSE は closesocket が呼び出された後には投稿されません。
- FD_QOS:
- WSAAsyncSelect が呼び出されたとき、ソケットに関連付けられた Quality of Service が変更されている場合。
- SIO_GET_QOS を指定した WSAIoctl が呼び出された後、Quality of Service が変更されたとき。
- FD_GROUP_QOS: 予約済み。
- FD_ROUTING_INTERFACE_CHANGE:
- SIO_ROUTING_INTERFACE_CHANGE を指定した WSAIoctl が呼び出された後、IOCTL で指定された宛先に到達するために使用すべきローカルインターフェイスが変更されたとき。
- FD_ADDRESS_LIST_CHANGE:
- SIO_ADDRESS_LIST_CHANGE を指定した WSAIoctl が呼び出された後、アプリケーションがバインドできるローカルアドレスのリストが変更されたとき。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)
各言語での呼び出し定義
// WS2_32.dll
#include <windows.h>
INT WSAAsyncSelect(
SOCKET s,
HWND hWnd,
DWORD wMsg,
INT lEvent
);[DllImport("WS2_32.dll", SetLastError = true, ExactSpelling = true)]
static extern int WSAAsyncSelect(
UIntPtr s, // SOCKET
IntPtr hWnd, // HWND
uint wMsg, // DWORD
int lEvent // INT
);<DllImport("WS2_32.dll", SetLastError:=True, ExactSpelling:=True)>
Public Shared Function WSAAsyncSelect(
s As UIntPtr, ' SOCKET
hWnd As IntPtr, ' HWND
wMsg As UInteger, ' DWORD
lEvent As Integer ' INT
) As Integer
End Function' s : SOCKET
' hWnd : HWND
' wMsg : DWORD
' lEvent : INT
Declare PtrSafe Function WSAAsyncSelect Lib "ws2_32" ( _
ByVal s As LongPtr, _
ByVal hWnd As LongPtr, _
ByVal wMsg As Long, _
ByVal lEvent As Long) As Long
' VBA7前提(PtrSafe)。32bit Office では LongPtr→Long。Integer=16bit / Long=32bit / LongLong=64bit。import ctypes
from ctypes import wintypes
WSAAsyncSelect = ctypes.windll.ws2_32.WSAAsyncSelect
WSAAsyncSelect.restype = ctypes.c_int
WSAAsyncSelect.argtypes = [
ctypes.c_size_t, # s : SOCKET
wintypes.HANDLE, # hWnd : HWND
wintypes.DWORD, # wMsg : DWORD
ctypes.c_int, # lEvent : INT
]
# GetLastError: use ctypes.GetLastError() (or ctypes.WinDLL(use_last_error=True))require 'fiddle'
require 'fiddle/import'
lib = Fiddle.dlopen('WS2_32.dll')
WSAAsyncSelect = Fiddle::Function.new(
lib['WSAAsyncSelect'],
[
Fiddle::TYPE_UINTPTR_T, # s : SOCKET
Fiddle::TYPE_VOIDP, # hWnd : HWND
-Fiddle::TYPE_INT, # wMsg : DWORD
Fiddle::TYPE_INT, # lEvent : INT
],
Fiddle::TYPE_INT)#[link(name = "ws2_32")]
extern "system" {
fn WSAAsyncSelect(
s: usize, // SOCKET
hWnd: *mut core::ffi::c_void, // HWND
wMsg: u32, // DWORD
lEvent: i32 // INT
) -> i32;
}
// crates: windows-sys provides ready-made bindings for this API.$sig = @"
[DllImport("WS2_32.dll", SetLastError = true)]
public static extern int WSAAsyncSelect(UIntPtr s, IntPtr hWnd, uint wMsg, int lEvent);
"@
$api = Add-Type -MemberDefinition $sig -Name 'WS2_32_WSAAsyncSelect' -Namespace Win32 -PassThru
# $api::WSAAsyncSelect(s, hWnd, wMsg, lEvent)#uselib "WS2_32.dll"
#func global WSAAsyncSelect "WSAAsyncSelect" sptr, sptr, sptr, sptr
; WSAAsyncSelect s, hWnd, wMsg, lEvent ; 戻り値は stat
; s : SOCKET -> "sptr"
; hWnd : HWND -> "sptr"
; wMsg : DWORD -> "sptr"
; lEvent : INT -> "sptr"
; ※HSP3.7は #func のため戻り値はシステム変数 stat に格納されます。#uselib "WS2_32.dll"
#cfunc global WSAAsyncSelect "WSAAsyncSelect" sptr, sptr, int, int
; res = WSAAsyncSelect(s, hWnd, wMsg, lEvent)
; s : SOCKET -> "sptr"
; hWnd : HWND -> "sptr"
; wMsg : DWORD -> "int"
; lEvent : INT -> "int"; INT WSAAsyncSelect(SOCKET s, HWND hWnd, DWORD wMsg, INT lEvent)
#uselib "WS2_32.dll"
#cfunc global WSAAsyncSelect "WSAAsyncSelect" intptr, intptr, int, int
; res = WSAAsyncSelect(s, hWnd, wMsg, lEvent)
; s : SOCKET -> "intptr"
; hWnd : HWND -> "intptr"
; wMsg : DWORD -> "int"
; lEvent : INT -> "int"import (
"golang.org/x/sys/windows"
"unsafe"
)
var (
ws2_32 = windows.NewLazySystemDLL("WS2_32.dll")
procWSAAsyncSelect = ws2_32.NewProc("WSAAsyncSelect")
)
// s (SOCKET), hWnd (HWND), wMsg (DWORD), lEvent (INT)
r1, _, err := procWSAAsyncSelect.Call(
uintptr(s),
uintptr(hWnd),
uintptr(wMsg),
uintptr(lEvent),
)
_ = err // syscall.Errno (valid when the call sets last-error)
_ = r1 // INTfunction WSAAsyncSelect(
s: NativeUInt; // SOCKET
hWnd: THandle; // HWND
wMsg: DWORD; // DWORD
lEvent: Integer // INT
): Integer; stdcall;
external 'WS2_32.dll' name 'WSAAsyncSelect';result := DllCall("WS2_32\WSAAsyncSelect"
, "UPtr", s ; SOCKET
, "Ptr", hWnd ; HWND
, "UInt", wMsg ; DWORD
, "Int", lEvent ; INT
, "Int") ; return: INT●WSAAsyncSelect(s, hWnd, wMsg, lEvent) = DLL("WS2_32.dll", "int WSAAsyncSelect(int, void*, dword, int)")
# 呼び出し: WSAAsyncSelect(s, hWnd, wMsg, lEvent)
# s : SOCKET -> "int"
# hWnd : HWND -> "void*"
# wMsg : DWORD -> "dword"
# lEvent : INT -> "int"
# なでしこ1は32bit・ANSI(Shift_JIS)。文字列=char*(ANSI)、ポインタ/ハンドル=void*(4byte)。const std = @import("std");
extern "ws2_32" fn WSAAsyncSelect(
s: usize, // SOCKET
hWnd: ?*anyopaque, // HWND
wMsg: u32, // DWORD
lEvent: i32 // INT
) callconv(std.os.windows.WINAPI) i32;proc WSAAsyncSelect(
s: uint, # SOCKET
hWnd: pointer, # HWND
wMsg: uint32, # DWORD
lEvent: int32 # INT
): int32 {.importc: "WSAAsyncSelect", stdcall, dynlib: "WS2_32.dll".}pragma(lib, "ws2_32");
extern(Windows)
int WSAAsyncSelect(
size_t s, // SOCKET
void* hWnd, // HWND
uint wMsg, // DWORD
int lEvent // INT
);ccall((:WSAAsyncSelect, "WS2_32.dll"), stdcall, Int32,
(Csize_t, Ptr{Cvoid}, UInt32, Int32),
s, hWnd, wMsg, lEvent)
# s : SOCKET -> Csize_t
# hWnd : HWND -> Ptr{Cvoid}
# wMsg : DWORD -> UInt32
# lEvent : INT -> Int32
# stdcall は 32bit のみ意味を持つ(x64 では無視)。local ffi = require("ffi")
ffi.cdef[[
int32_t WSAAsyncSelect(
uintptr_t s,
void* hWnd,
uint32_t wMsg,
int32_t lEvent);
]]
local ws2_32 = ffi.load("ws2_32")
-- ws2_32.WSAAsyncSelect(s, hWnd, wMsg, lEvent)
-- s : SOCKET
-- hWnd : HWND
-- wMsg : DWORD
-- lEvent : INT
-- 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。const koffi = require('koffi');
const lib = koffi.load('WS2_32.dll');
const WSAAsyncSelect = lib.func('__stdcall', 'WSAAsyncSelect', 'int32_t', ['uintptr_t', 'void *', 'uint32_t', 'int32_t']);
// WSAAsyncSelect(s, hWnd, wMsg, lEvent)
// s : SOCKET -> 'uintptr_t'
// hWnd : HWND -> 'void *'
// wMsg : DWORD -> 'uint32_t'
// lEvent : INT -> 'int32_t'
// 出力ポインタは koffi.out(...) で包む。構造体は koffi.struct で定義。const lib = Deno.dlopen("WS2_32.dll", {
WSAAsyncSelect: { parameters: ["usize", "pointer", "u32", "i32"], result: "i32" },
});
// lib.symbols.WSAAsyncSelect(s, hWnd, wMsg, lEvent)
// s : SOCKET -> "usize"
// hWnd : HWND -> "pointer"
// wMsg : DWORD -> "u32"
// lEvent : INT -> "i32"
// 文字列引数は "buffer"(NUL 終端のバイト列を Uint8Array で渡す)。
// 値渡し構造体は { struct: [ ...field types... ] } を使用。<?php
$ffi = FFI::cdef(<<<C
int32_t WSAAsyncSelect(
size_t s,
void* hWnd,
uint32_t wMsg,
int32_t lEvent);
C, "WS2_32.dll");
// $ffi->WSAAsyncSelect(s, hWnd, wMsg, lEvent);
// s : SOCKET
// hWnd : HWND
// wMsg : DWORD
// lEvent : INT
// 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
// WINAPI(stdcall): x64 では呼出規約が統一されるため問題なし。x86 では __stdcall 対応のラッパが必要な場合あり。import com.sun.jna.*;
import com.sun.jna.ptr.*;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;
public interface Ws2_32 extends StdCallLibrary {
Ws2_32 INSTANCE = Native.load("ws2_32", Ws2_32.class);
int WSAAsyncSelect(
long s, // SOCKET
Pointer hWnd, // HWND
int wMsg, // DWORD
int lEvent // INT
);
}@[Link("ws2_32")]
lib LibWS2_32
fun WSAAsyncSelect = WSAAsyncSelect(
s : LibC::SizeT, # SOCKET
hWnd : Void*, # HWND
wMsg : UInt32, # DWORD
lEvent : Int32 # INT
) : Int32
end
# 構造体/GUID/enum は lib 内に対応する型定義が必要。
# 呼出規約: x64 は規約統一のため OK。x86(32bit)は WINAPI=stdcall だが Crystal の fun に stdcall 付与構文がなく非対応。import 'dart:ffi';
import 'package:ffi/ffi.dart';
typedef WSAAsyncSelectNative = Int32 Function(UintPtr, Pointer<Void>, Uint32, Int32);
typedef WSAAsyncSelectDart = int Function(int, Pointer<Void>, int, int);
final WSAAsyncSelect = DynamicLibrary.open('WS2_32.dll')
.lookupFunction<WSAAsyncSelectNative, WSAAsyncSelectDart>('WSAAsyncSelect');
// s : SOCKET -> UintPtr
// hWnd : HWND -> Pointer<Void>
// wMsg : DWORD -> Uint32
// lEvent : INT -> Int32
// 文字列は package:ffi の "...".toNativeUtf16()/toNativeUtf8() で変換。{$mode objfpc}{$H+}
function WSAAsyncSelect(
s: NativeUInt; // SOCKET
hWnd: THandle; // HWND
wMsg: DWORD; // DWORD
lEvent: Integer // INT
): Integer; stdcall;
external 'WS2_32.dll' name 'WSAAsyncSelect';import Foreign
import Foreign.C.Types
import Foreign.C.String
foreign import stdcall safe "WSAAsyncSelect"
c_WSAAsyncSelect :: CUIntPtr -> Ptr () -> Word32 -> Int32 -> IO Int32
-- s : SOCKET -> CUIntPtr
-- hWnd : HWND -> Ptr ()
-- wMsg : DWORD -> Word32
-- lEvent : INT -> Int32
-- 要 GHC(Windows)。stdcall は x64 では ccall として扱われる。ブロックする API は safe 呼び出し推奨。open Ctypes
open Foreign
let wsaasyncselect =
foreign "WSAAsyncSelect"
(size_t @-> (ptr void) @-> uint32_t @-> int32_t @-> returning int32_t)
(* s : SOCKET -> size_t *)
(* hWnd : HWND -> (ptr void) *)
(* wMsg : DWORD -> uint32_t *)
(* lEvent : INT -> int32_t *)
(* foreign は cdecl 前提。x64 Windows では WINAPI と一致。構造体は ctypes structure を定義のこと。 *)(cffi:define-foreign-library ws2_32 (t "WS2_32.dll"))
(cffi:use-foreign-library ws2_32)
(cffi:defcfun ("WSAAsyncSelect" wsaasync-select :convention :stdcall) :int32
(s :uint64) ; SOCKET
(h-wnd :pointer) ; HWND
(w-msg :uint32) ; DWORD
(l-event :int32)) ; INT
; isize/usize(INT_PTR/SIZE_T)は x64 前提で :int64/:uint64。x86 では :int32/:uint32。use Win32::API;
my $WSAAsyncSelect = Win32::API::More->new('WS2_32',
'int WSAAsyncSelect(WPARAM s, HANDLE hWnd, DWORD wMsg, int lEvent)');
# my $ret = $WSAAsyncSelect->Call($s, $hWnd, $wMsg, $lEvent);
# s : SOCKET -> WPARAM
# hWnd : HWND -> HANDLE
# wMsg : DWORD -> DWORD
# lEvent : INT -> int
# 値渡し構造体は pack() した文字列、または Win32::API::Struct を使用。関連項目
- f WSAEventSelect — ソケットのネットワークイベントをイベントオブジェクトに関連付ける。
- f select — 複数ソケットの入出力可否を監視する。