Win32 API 日本語リファレンス
ホームNetworking.WinSock › getaddrinfo

getaddrinfo

関数
ホスト名やサービス名からアドレス情報を解決する。
DLLWS2_32.dll呼出規約winapiSetLastErrorあり対応OSWindows 8.1 以降

シグネチャ

// WS2_32.dll
#include <windows.h>

INT getaddrinfo(
    LPCSTR pNodeName,   // optional
    LPCSTR pServiceName,   // optional
    const ADDRINFOA* pHints,   // optional
    ADDRINFOA** ppResult
);

パラメーター

名前方向説明
pNodeNameLPCSTRinoptionalホスト(ノード)名、または数値のホストアドレス文字列を格納した NULL 終端の ANSI 文字列へのポインターです。インターネットプロトコルの場合、数値のホストアドレス文字列はドット区切りの 10 進 IPv4 アドレス、または IPv6 の 16 進アドレスです。
pServiceNameLPCSTRinoptional

サービス名、または文字列として表現されたポート番号のいずれかを格納した NULL 終端の ANSI 文字列へのポインターです。

サービス名はポート番号に対する文字列の別名です。たとえば「http」はポート 80 の別名であり、これは Internet Engineering Task Force (IETF) によって HTTP プロトコル用に Web サーバーが使用する既定のポートとして定義されています。ポート番号を指定しない場合に pServiceName パラメーターに指定できる値は、次のファイルに一覧があります。

%WINDIR%\system32\drivers\etc\services

pHintsADDRINFOA*inoptional

呼び出し元がサポートするソケットの種類に関するヒントを提供する addrinfo 構造体へのポインターです。

pHints パラメーターが指す addrinfo 構造体の ai_addrlenai_canonnameai_addrai_next の各メンバーは、0 または NULL でなければなりません。そうでない場合、GetAddrInfoEx 関数は WSANO_RECOVERY で失敗します。

詳細については「解説」を参照してください。

ppResultADDRINFOA**outホストに関する応答情報を格納した、1 つ以上の addrinfo 構造体のリンクリストへのポインターです。

戻り値の型: INT

公式ドキュメント

ANSI ホスト名からアドレスへの、プロトコルに依存しない変換を行います。

戻り値

成功した場合は 0 を返します。失敗した場合は、 Windows ソケットエラーコードに記載されている、0 以外の Windows ソケットエラーコードを返します。

getaddrinfo 関数が返す 0 以外のエラーコードのほとんどは、Internet Engineering Task Force (IETF) の推奨事項で示されている一連のエラーに対応しています。次の表に、これらのエラーコードとそれに対応する WSA エラーコードを示します。WSA エラーコードは Winsock プログラマーにとってなじみがあり包括的なエラー情報を提供するため、WSA エラーコードの使用を推奨します。

エラー値 WSA 相当 説明
EAI_AGAIN WSATRY_AGAIN 名前解決で一時的な障害が発生しました。
EAI_BADFLAGS WSAEINVAL pHints パラメーターの ai_flags メンバーに無効な値が指定されました。
EAI_FAIL WSANO_RECOVERY 名前解決で回復不能な障害が発生しました。
EAI_FAMILY WSAEAFNOSUPPORT pHints パラメーターの ai_family メンバーがサポートされていません。
EAI_MEMORY WSA_NOT_ENOUGH_MEMORY メモリの割り当てに失敗しました。
EAI_NONAME WSAHOST_NOT_FOUND 指定されたパラメーターで名前を解決できなかったか、pNodeName パラメーターと pServiceName パラメーターのいずれも指定されませんでした。
EAI_SERVICE WSATYPE_NOT_FOUND 指定された pHints パラメーターの ai_socktype メンバーでは、pServiceName パラメーターがサポートされていません。
EAI_SOCKTYPE WSAESOCKTNOSUPPORT pHints パラメーターの ai_socktype メンバーがサポートされていません。

getaddrinfo 関数が返す EAI コードに基づいてエラーメッセージを表示するには、 gai_strerror 関数を使用します。 gai_strerror 関数は IETF の推奨事項に準拠するために提供されていますが、スレッドセーフではありません。そのため、 WSAGetLastError などの従来の Windows ソケット関数の使用を推奨します。

エラーコード 意味
WSA_NOT_ENOUGH_MEMORY
操作を実行するのに十分なメモリがありませんでした。
WSAEAFNOSUPPORT
要求されたプロトコルと互換性のないアドレスが使用されました。このエラーは、pHints パラメーターが指す addrinfo 構造体の ai_family メンバーがサポートされていない場合に返されます。
WSAEINVAL
無効な引数が指定されました。このエラーは、pHints パラメーターが指す addrinfo 構造体の ai_flags メンバーに無効な値が指定された場合に返されます。
WSAESOCKTNOSUPPORT
このアドレスファミリでは、指定されたソケットの種類はサポートされていません。このエラーは、pHints パラメーターが指す addrinfo 構造体の ai_socktype メンバーがサポートされていない場合に返されます。
WSAHOST_NOT_FOUND
そのようなホストは存在しません。このエラーは、指定されたパラメーターで名前を解決できなかったか、pNodeName パラメーターと pServiceName パラメーターのいずれも指定されなかった場合に返されます。
WSANO_DATA
要求された名前は有効ですが、要求された種類のデータは見つかりませんでした。
WSANO_RECOVERY
データベース検索中に回復不能なエラーが発生しました。このエラーは、名前解決で回復不能なエラーが発生した場合に返されます。
WSANOTINITIALISED
この関数を使用する前に、 WSAStartup の呼び出しが成功している必要があります。
WSATRY_AGAIN
これは通常、ホスト名解決中の一時的なエラーであり、ローカルサーバーが権威サーバーから応答を受け取らなかったことを意味します。このエラーは、名前解決で一時的な障害が発生した場合に返されます。
WSATYPE_NOT_FOUND
指定されたクラスが見つかりませんでした。pHints パラメーターが指す addrinfo 構造体の指定された ai_socktype メンバーでは、pServiceName パラメーターがサポートされていません。

解説(Remarks)

getaddrinfo 関数は、ホスト名からアドレスへのプロトコルに依存しない変換を行う関数の ANSI 版です。この関数の Unicode 版は GetAddrInfoW です。開発者には、getaddrinfo ANSI 関数ではなく GetAddrInfoW Unicode 関数の使用を推奨します。

getaddrinfo 関数は NS_DNS 名前空間の結果を返します。複数の名前空間プロバイダーが情報を返した場合、getaddrinfo 関数はすべての応答を集約します。IPv6 および IPv4 プロトコルで使用する場合、名前解決は Domain Name System (DNS)、ローカルの hosts ファイル、または NS_DNS 名前空間のその他の名前付けメカニズムによって行われます。

getaddrinfo 関数に使用できる別名として GetAddrInfoA もあります。Ws2tcpip.h ヘッダーファイル内のマクロにより、GetAddrInfoAgetaddrinfo として定義されます。

Ws2tcpip.h ヘッダーファイル内のマクロは、大文字と小文字が混在する関数名 GetAddrInfoADDRINFOT 構造体を定義します。この GetAddrInfo 関数は、pNodeName および pServiceName パラメーターに TCHAR 型のポインターを、pHints および ppResult パラメーターに ADDRINFOT 型のポインターを指定して呼び出します。UNICODE または _UNICODE が定義されていない場合、GetAddrInfo は関数の ANSI 版である getaddrinfo として定義され、ADDRINFOTaddrinfo 構造体として定義されます。UNICODE または _UNICODE が定義されている場合、GetAddrInfo は関数の Unicode 版である GetAddrInfoW として定義され、ADDRINFOTaddrinfoW 構造体として定義されます。

Windows Server 2003 および Windows XP 向けの Platform Software Development Kit (SDK) の Ws2tcpip.h ヘッダーファイルで定義されている getaddrinfo 関数のパラメーター名およびパラメーターの型は、異なっていました。

pNodeName または pServiceName パラメーターの一方または両方が、NULL 終端の ANSI 文字列を指している必要があります。通常は両方を指定します。

成功すると、ppResult パラメーターに addrinfo 構造体のリンクリストが返されます。このリストは、返された各 addrinfo 構造体の ai_next メンバーが指すポインターをたどり、NULL ポインターに達するまで処理できます。返される各 addrinfo 構造体の ai_familyai_socktypeai_protocol の各メンバーは、 socket または WSASocket 関数呼び出しのそれぞれの引数に対応します。また、返される各 addrinfo 構造体の ai_addr メンバーは、内容が設定されたソケットアドレス構造体を指し、その長さは ai_addrlen メンバーで指定されます。

pNodeName パラメーターがコンピューター名を指している場合、そのコンピューターの送信元アドレスとして使用できるすべての永続アドレスが返されます。Windows Vista 以降では、これらのアドレスには、GetUnicastIpAddressTable 関数または GetUnicastIpAddressEntry 関数が返すすべてのユニキャスト IP アドレスのうち、MIB_UNICASTIPADDRESS_ROW 構造体の SkipAsSource メンバーが false に設定されているものが含まれます。

pNodeName パラメーターが "localhost" に等しい文字列を指している場合、ローカルコンピューター上のすべてのループバックアドレスが返されます。

pNodeName パラメーターが空文字列を含む場合、ローカルコンピューター上に登録されているすべてのアドレスが返されます。

Windows Server 2003 以降では、pNodeName パラメーターが "..localmachine" に等しい文字列を指している場合、ローカルコンピューター上に登録されているすべてのアドレスが返されます。

pNodeName パラメーターがクラスター仮想サーバー名を参照している場合、仮想サーバーのアドレスのみが返されます。Windows Vista 以降では、これらのアドレスには、GetUnicastIpAddressTable 関数または GetUnicastIpAddressEntry 関数が返すすべてのユニキャスト IP アドレスのうち、MIB_UNICASTIPADDRESS_ROW 構造体の SkipAsSource メンバーが true に設定されているものが含まれます。クラスタリングの詳細については、Windows クラスタリングを参照してください。

Windows 7 Service Pack 1 (SP1) および Windows Server 2008 R2 Service Pack 1 (SP1) では、IP アドレスに SkipAsSource 属性を設定するためのサポートが Netsh.exe に追加されました。これに伴い、MIB_UNICASTIPADDRESS_ROW 構造体の SkipAsSource メンバーが false に設定されている場合は IP アドレスが DNS に登録され、SkipAsSource メンバーが true に設定されている場合は IP アドレスが DNS に登録されないように動作も変更されました。

Windows 7 および Windows Server 2008 R2 向けには、IP アドレスに SkipAsSource 属性を設定するためのサポートを Netsh.exe に追加する修正プログラムが提供されています。この修正プログラムでも、MIB_UNICASTIPADDRESS_ROW 構造体の SkipAsSource メンバーが false に設定されている場合は IP アドレスが DNS に登録され、SkipAsSource メンバーが true に設定されている場合は IP アドレスが DNS に登録されないように動作が変更されます。詳細については、サポート技術情報 (KB) 2386184 を参照してください。

同様の修正プログラムは、Windows Vista Service Pack 2 (SP2) および Windows Server 2008 Service Pack 2 (SP2) 向けにも提供されており、IP アドレスに SkipAsSource 属性を設定するためのサポートを Netsh.exe に追加します。この修正プログラムでも、MIB_UNICASTIPADDRESS_ROW 構造体の SkipAsSource メンバーが false に設定されている場合は IP アドレスが DNS に登録され、SkipAsSource メンバーが true に設定されている場合は IP アドレスが DNS に登録されないように動作が変更されます。

getaddrinfo 関数の呼び出し元は、pHints パラメーターが指す addrinfo 構造体を通じて、サポートするソケットの種類に関するヒントを提供できます。pHints パラメーターを使用する場合、それに関連付けられた addrinfo 構造体には次の規則が適用されます。

ai_family の値が AF_UNSPEC の場合、呼び出し元が任意のプロトコルファミリを受け入れることを示します。この値を使用すると、pNodeName パラメーターが指すホスト名について IPv4 と IPv6 の両方のアドレスを返すことができます。Windows Server 2003 および Windows XP では、IPv6 アドレスはローカルコンピューターに IPv6 がインストールされている場合にのみ返されます。

pHints パラメーターに指定する addrinfo 構造体のその他の値は、特定の要件を示します。たとえば、呼び出し元が IPv4 のみを扱い IPv6 を扱わない場合は、ai_family メンバーを AF_INET に設定します。別の例として、呼び出し元が TCP のみを扱い UDP を扱わない場合は、ai_socktype メンバーを SOCK_STREAM に設定します。

pHints パラメーターが NULL ポインターの場合、getaddrinfo 関数は、pHints 内の addrinfo 構造体が、ai_family メンバーを AF_UNSPEC に、その他のすべてのメンバーを 0 に設定して初期化されたかのように扱います。

Windows Vista 以降で getaddrinfo がサービスから呼び出される場合、その操作がユーザープロセスからサービスを呼び出した結果であるならば、サービスはそのユーザーになりすます (impersonate) 必要があります。これはセキュリティを適切に適用するためです。

getaddrinfo 関数は、IP アドレスのテキスト文字列表現を、その IP アドレス用の sockaddr 構造体やその他の情報を格納した addrinfo 構造体に変換するためにも使用できます。このように使用するには、pNodeName パラメーターが指す文字列に IP アドレスのテキスト表現を含め、pHints パラメーターが指す addrinfo 構造体の ai_flags メンバーに AI_NUMERICHOST フラグを設定する必要があります。pNodeName パラメーターが指す文字列には、IPv4 または IPv6 アドレスのいずれかのテキスト表現を含めることができます。テキストの IP アドレスは、ppResult パラメーターが指す addrinfo 構造体に変換されます。返される addrinfo 構造体には、IP アドレス用の sockaddr 構造体と、その IP アドレスに関する追加情報が含まれます。Windows Server 2003 および Windows XP でこの方法を IPv6 アドレス文字列に対して使用するには、ローカルコンピューターに IPv6 プロトコルがインストールされている必要があります。インストールされていない場合は、WSAHOST_NOT_FOUND エラーが返されます。

動的に割り当てられたアドレス情報の解放

ppResult パラメーターが指す、getaddrinfo 関数によって返されるすべての情報は、すべての addrinfo 構造体、ソケットアドレス構造体、および addrinfo 構造体が指す正規ホスト名文字列を含め、動的に割り当てられます。この関数の呼び出しが成功して割り当てられたメモリは、後で freeaddrinfo を呼び出して解放する必要があります。

サンプルコード

次のコード例は、getaddrinfo 関数の使用方法を示しています。
#undef UNICODE

#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>

// link with Ws2_32.lib
#pragma comment (lib, "Ws2_32.lib")

int __cdecl main(int argc, char **argv)
{

    //-----------------------------------------
    // Declare and initialize variables
    WSADATA wsaData;
    int iResult;
    INT iRetval;

    DWORD dwRetval;

    int i = 1;
    
    struct addrinfo *result = NULL;
    struct addrinfo *ptr = NULL;
    struct addrinfo hints;

    struct sockaddr_in  *sockaddr_ipv4;
//    struct sockaddr_in6 *sockaddr_ipv6;
    LPSOCKADDR sockaddr_ip;

    char ipstringbuffer[46];
    DWORD ipbufferlength = 46;

    // Validate the parameters
    if (argc != 3) {
        printf("usage: %s <hostname> <servicename>\n", argv[0]);
        printf("getaddrinfo provides protocol-independent translation\n");
        printf("   from an ANSI host name to an IP address\n");
        printf("%s example usage\n", argv[0]);
        printf("   %s www.contoso.com 0\n", argv[0]);
        return 1;
    }

    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed: %d\n", iResult);
        return 1;
    }

    //--------------------------------
    // Setup the hints address info structure
    // which is passed to the getaddrinfo() function
    ZeroMemory( &hints, sizeof(hints) );
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    printf("Calling getaddrinfo with following parameters:\n");
    printf("\tnodename = %s\n", argv[1]);
    printf("\tservname (or port) = %s\n\n", argv[2]);
    
//--------------------------------
// Call getaddrinfo(). If the call succeeds,
// the result variable will hold a linked list
// of addrinfo structures containing response
// information
    dwRetval = getaddrinfo(argv[1], argv[2], &hints, &result);
    if ( dwRetval != 0 ) {
        printf("getaddrinfo failed with error: %d\n", dwRetval);
        WSACleanup();
        return 1;
    }

    printf("getaddrinfo returned success\n");
    
    // Retrieve each address and print out the hex bytes
    for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {

        printf("getaddrinfo response %d\n", i++);
        printf("\tFlags: 0x%x\n", ptr->ai_flags);
        printf("\tFamily: ");
        switch (ptr->ai_family) {
            case AF_UNSPEC:
                printf("Unspecified\n");
                break;
            case AF_INET:
                printf("AF_INET (IPv4)\n");
                sockaddr_ipv4 = (struct sockaddr_in *) ptr->ai_addr;
                printf("\tIPv4 address %s\n",
                    inet_ntoa(sockaddr_ipv4->sin_addr) );
                break;
            case AF_INET6:
                printf("AF_INET6 (IPv6)\n");
                // the InetNtop function is available on Windows Vista and later
                // sockaddr_ipv6 = (struct sockaddr_in6 *) ptr->ai_addr;
                // printf("\tIPv6 address %s\n",
                //    InetNtop(AF_INET6, &sockaddr_ipv6->sin6_addr, ipstringbuffer, 46) );
                
                // We use WSAAddressToString since it is supported on Windows XP and later
                sockaddr_ip = (LPSOCKADDR) ptr->ai_addr;
                // The buffer length is changed by each call to WSAAddresstoString
                // So we need to set it for each iteration through the loop for safety
                ipbufferlength = 46;
                iRetval = WSAAddressToString(sockaddr_ip, (DWORD) ptr->ai_addrlen, NULL, 
                    ipstringbuffer, &ipbufferlength );
                if (iRetval)
                    printf("WSAAddressToString failed with %u\n", WSAGetLastError() );
                else    
                    printf("\tIPv6 address %s\n", ipstringbuffer);
                break;
            case AF_NETBIOS:
                printf("AF_NETBIOS (NetBIOS)\n");
                break;
            default:
                printf("Other %ld\n", ptr->ai_family);
                break;
        }
        printf("\tSocket type: ");
        switch (ptr->ai_socktype) {
            case 0:
                printf("Unspecified\n");
                break;
            case SOCK_STREAM:
                printf("SOCK_STREAM (stream)\n");
                break;
            case SOCK_DGRAM:
                printf("SOCK_DGRAM (datagram) \n");
                break;
            case SOCK_RAW:
                printf("SOCK_RAW (raw) \n");
                break;
            case SOCK_RDM:
                printf("SOCK_RDM (reliable message datagram)\n");
                break;
            case SOCK_SEQPACKET:
                printf("SOCK_SEQPACKET (pseudo-stream packet)\n");
                break;
            default:
                printf("Other %ld\n", ptr->ai_socktype);
                break;
        }
        printf("\tProtocol: ");
        switch (ptr->ai_protocol) {
            case 0:
                printf("Unspecified\n");
                break;
            case IPPROTO_TCP:
                printf("IPPROTO_TCP (TCP)\n");
                break;
            case IPPROTO_UDP:
                printf("IPPROTO_UDP (UDP) \n");
                break;
            default:
                printf("Other %ld\n", ptr->ai_protocol);
                break;
        }
        printf("\tLength of this sockaddr: %d\n", ptr->ai_addrlen);
        printf("\tCanonical name: %s\n", ptr->ai_canonname);
    }

    freeaddrinfo(result);
    WSACleanup();

    return 0;
}
注意 開発環境が、addrinfo および getaddrinfo の構造体定義と関数定義を含む最新バージョンの Ws2tcpip.h を対象としていることを確認してください。

国際化ドメイン名

インターネットのホスト名は通常、非常に限られた文字セットで構成されます。

インターネットの普及に伴い、ASCII 文字セットで表現されないその他の言語のインターネットホスト名を識別する必要性が高まっています。このニーズに応え、非 ASCII 文字 (Unicode) を特別な ASCII 文字列として表現できるようにする識別子は、国際化ドメイン名 (IDN: Internationalized Domain Names) と呼ばれます。IDN を標準的な方法で処理するために、アプリケーションにおけるドメイン名の国際化 (IDNA: Internationalizing Domain Names in Applications) と呼ばれるメカニズムが使用されます。IDN および IDNA の仕様は、Internet Engineering Task Force (IETF) が公開している RFC 3490RTF 5890RFC 6365 に文書化されています。

Windows 8 および Windows Server 2012 では、getaddrinfo 関数は、pNodeName パラメーターに渡された名前に適用される国際化ドメイン名 (IDN) の解析をサポートします。Winsock は Punycode/IDN のエンコードと変換を行います。この動作は、後述する AI_DISABLE_IDN_ENCODING フラグを使用して無効にできます。

Windows 7 および Windows Server 2008 R2 以前では、getaddrinfo 関数は、現在のところ pNodeName パラメーターに渡された名前に適用される IDN 解析をサポートしていません。Winsock は Punycode/IDN 変換を一切行いません。ワイド文字版の GetAddrInfo 関数は、RFC 3490 に従って IDN を変換するために Punycode を使用することはありません。ワイド文字版の GetAddrInfo 関数は、DNS にクエリを行う際、Unicode 名を、エンタープライズ環境の Microsoft DNS サーバーが使用する形式である UTF-8 形式でエンコードします。

Windows Vista 以降のいくつかの関数は、IDN 内の Unicode ラベルとそれに相当する ASCII 表現との間の変換をサポートします。変換後の各 Unicode ラベルの表現は ASCII 文字のみで構成され、Unicode ラベルに非 ASCII 文字が含まれていた場合は xn-- というプレフィックスで始まります。これは、一部の DNS ツールやサーバーが ASCII 文字のみをサポートするため、インターネット上の既存の DNS サーバーをサポートするためです (RFC 3490 を参照)。

IdnToAscii 関数は、RFC 3490 で定義された標準アルゴリズムを使用して、Punycode によって IDN を元の Unicode 文字列の ASCII 表現に変換します。IdnToUnicode 関数は、IDN の ASCII 形式を通常の Unicode UTF-16 エンコード構文に変換します。詳細および関連するドラフト標準へのリンクについては、国際化ドメイン名 (IDN) の処理を参照してください。

IdnToAscii 関数を使用して IDN 名を ASCII 形式に変換し、それを pNodeName パラメーターとして getaddrinfo 関数に渡すことができます。ワイド文字版のこの関数を使用する場合 (UNICODE または _UNICODE が定義されている場合) に、この IDN 名を GetAddrInfo 関数に渡すには、MultiByteToWideChar 関数を使用して CHAR 文字列を WCHAR 文字列に変換します。

pHints パラメーターでの ai_flags の使用

pHints パラメーターに指定する省略可能な addrinfo 構造体の ai_flags メンバーのフラグは、関数の動作を変更します。

これらのフラグビットは、Windows 7 向けの Microsoft Windows Software Development Kit (SDK) の Ws2def.h ヘッダーファイルで定義されています。Windows Server 2008 および Windows Vista 向けの Windows SDK では、これらのフラグビットは Ws2tcpip.h ヘッダーファイルで定義されています。Windows Server 2003 および Windows XP 向けの Platform SDK では、これらのフラグビットは Ws2tcpip.h ヘッダーファイルで定義されています。

フラグビットには、次のものを組み合わせて指定できます。

フラグビット 説明
AI_PASSIVE AI_PASSIVE フラグを設定すると、呼び出し元が、返されたソケットアドレス構造体を bind 関数の呼び出しで使用する意図があることを示します。AI_PASSIVE フラグが設定され、かつ pNodeNameNULL ポインターの場合、ソケットアドレス構造体の IP アドレス部分は、IPv4 アドレスの場合は INADDR_ANY に、IPv6 アドレスの場合は IN6ADDR_ANY_INIT に設定されます。

AI_PASSIVE フラグが設定されていない場合、返されるソケットアドレス構造体は、コネクション指向プロトコルでは connect 関数の呼び出しに、コネクションレスプロトコルでは connectsendto、または send 関数のいずれかの呼び出しに使用できる状態になります。この場合に pNodeName パラメーターが NULL ポインターであれば、ソケットアドレス構造体の IP アドレス部分はループバックアドレスに設定されます。

AI_CANONNAME AI_CANONNAMEAI_NUMERICHOST のいずれも使用されていない場合、 getaddrinfo 関数は解決を試みます。リテラル文字列が渡された場合、 getaddrinfo はその文字列の変換を試み、ホスト名が渡された場合、 getaddrinfo 関数はその名前を 1 つまたは複数のアドレスに解決しようとします。

AI_CANONNAME ビットが設定されている場合、pNodeName パラメーターを NULL にすることはできません。そうでない場合、 getaddrinfo 関数は WSANO_RECOVERY で失敗します。

AI_CANONNAME ビットが設定され、かつ getaddrinfo 関数が成功を返した場合、ppResult パラメーターの ai_canonname メンバーは、指定されたノードの正規名を格納した NULL 終端文字列を指します。

注意 getaddrinfo 関数は、AI_CANONNAME フラグが設定されている場合でも、関連する addrinfo 構造体の ai_canonname メンバーが NULL のまま成功を返すことがあります。したがって、AI_CANONNAME フラグを使用する際は、関連する addrinfo 構造体の ai_canonname メンバーが NULL かどうかをテストすることを推奨します。
AI_NUMERICHOST AI_NUMERICHOST ビットが設定されている場合、pNodeName パラメーターには NULL 以外の数値ホストアドレス文字列を含める必要があります。そうでない場合は EAI_NONAME エラーが返されます。このフラグは、名前解決サービスが呼び出されるのを防ぎます。
AI_NUMERICSERV AI_NUMERICSERV ビットが設定されている場合、pServiceName パラメーターには NULL 以外の数値ポート番号を含める必要があります。そうでない場合は EAI_NONAME エラーが返されます。このフラグは、名前解決サービスが呼び出されるのを防ぎます。

AI_NUMERICSERV フラグは、Windows Vista 以降の Windows SDK で定義されています。AI_NUMERICSERV フラグは Microsoft のプロバイダーではサポートされていません。

AI_ALL AI_ALL ビットが設定されている場合、IPv6 アドレスと、AI_V4MAPPED を伴う IPv4 アドレスの両方が要求されます。

AI_ALL フラグは、Windows Vista 以降の Windows SDK で定義されています。AI_ALL フラグは Windows Vista 以降でサポートされます。

AI_ADDRCONFIG AI_ADDRCONFIG ビットが設定されている場合、getaddrinfo はグローバルアドレスが構成されている場合にのみ解決を行います。AI_ADDRCONFIG フラグが指定されている場合、IPv4 アドレスはローカルシステムに IPv4 アドレスが構成されている場合にのみ返され、IPv6 アドレスはローカルシステムに IPv6 アドレスが構成されている場合にのみ返されます。IPv4 または IPv6 のループバックアドレスは、有効なグローバルアドレスとは見なされません。

AI_ADDRCONFIG フラグは、Windows Vista 以降の Windows SDK で定義されています。AI_ADDRCONFIG フラグは Windows Vista 以降でサポートされます。

AI_V4MAPPED AI_V4MAPPED ビットが設定されていて IPv6 アドレスの要求が失敗した場合、IPv4 アドレスに対する名前サービス要求が行われ、それらのアドレスは IPv4 マップ IPv6 アドレス形式に変換されます。

AI_V4MAPPED フラグは、Windows Vista 以降の Windows SDK で定義されています。AI_V4MAPPED フラグは Windows Vista 以降でサポートされます。

AI_NON_AUTHORITATIVE AI_NON_AUTHORITATIVE ビットが設定されている場合、NS_EMAIL 名前空間プロバイダーは権威ある結果と権威のない結果の両方を返します。AI_NON_AUTHORITATIVE ビットが設定されていない場合、NS_EMAIL 名前空間プロバイダーは権威ある結果のみを返します。

AI_NON_AUTHORITATIVE フラグは、Windows Vista 以降の Windows SDK で定義されています。AI_NON_AUTHORITATIVE フラグは Windows Vista 以降でサポートされ、NS_EMAIL 名前空間にのみ適用されます。

AI_SECURE AI_SECURE ビットが設定されている場合、NS_EMAIL 名前空間プロバイダーは、なりすましの可能性を最小限に抑えるために強化されたセキュリティで取得された結果を返します。

AI_SECURE フラグは、Windows Vista 以降の Windows SDK で定義されています。AI_SECURE フラグは Windows Vista 以降でサポートされ、NS_EMAIL 名前空間にのみ適用されます。

AI_RETURN_PREFERRED_NAMES AI_RETURN_PREFERRED_NAMES が設定されている場合、pNodeName パラメーターに名前を指定してはなりません。NS_EMAIL 名前空間プロバイダーは、公開用の優先名を返します。

AI_RETURN_PREFERRED_NAMES フラグは、Windows Vista 以降の Windows SDK で定義されています。AI_RETURN_PREFERRED_NAMES フラグは Windows Vista 以降でサポートされ、NS_EMAIL 名前空間にのみ適用されます。

AI_FQDN AI_FQDN が設定されていて、フラットな名前 (単一ラベル) が指定されている場合、getaddrinfo は、その名前が最終的に解決された完全修飾ドメイン名を返します。完全修飾ドメイン名は、関連する addrinfo 構造体の ai_canonname メンバーに返されます。これは、DNS に登録された正規名を返す AI_CANONNAME ビットフラグとは異なり、その正規名は、フラットな名前が解決された完全修飾ドメイン名とは異なる場合があります。AI_FQDNAI_CANONNAME のビットは、いずれか一方しか設定できません。両方のフラグが存在する場合、getaddrinfo 関数は EAI_BADFLAGS で失敗します。

AI_FQDN ビットが設定されている場合、pNodeName パラメーターを NULL にすることはできません。そうでない場合、 GetAddrInfoEx 関数は WSANO_RECOVERY で失敗します。

Windows 7: AI_FQDN フラグは、Windows 7 以降の Windows SDK で定義されています。AI_FQDN フラグは Windows 7 以降でサポートされます。

AI_FILESERVER AI_FILESERVER が設定されている場合、これは、クエリ対象のホスト名がファイル共有のシナリオで使用されていることを名前空間プロバイダーに伝えるヒントです。名前空間プロバイダーはこのヒントを無視する場合があります。

Windows 7: AI_FILESERVER フラグは、Windows 7 以降の Windows SDK で定義されています。AI_FILESERVER フラグは Windows 7 以降でサポートされます。

AI_NUMERICHOST を使用したサンプルコード

次のコード例は、getaddrinfo 関数を使用して、IP アドレスのテキスト文字列表現を、その IP アドレス用の sockaddr 構造体やその他の情報を格納した addrinfo 構造体に変換する方法を示しています。
#undef UNICODE

#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>

// link with Ws2_32.lib
#pragma comment (lib, "Ws2_32.lib")

int __cdecl main(int argc, char **argv)
{

    //-----------------------------------------
    // Declare and initialize variables
    WSADATA wsaData;
    int iResult;

    DWORD dwRetval;

    int i = 1;
    
    struct addrinfo *result = NULL;
    struct addrinfo *ptr = NULL;
    struct addrinfo hints;


    // Validate the parameters
    if (argc != 2) {
        printf("usage: %s <IP Address String>\n", argv[0]);
        printf("  getaddrinfo determines the IP binary network address\n");
        printf("       %s 207.46.197.32\n", argv[0]);  /* www.contoso.com */
        return 1;
    }
    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed: %d\n", iResult);
        return 1;
    }

    //--------------------------------
    // Setup the hints address info structure
    // which is passed to the getaddrinfo() function
    ZeroMemory( &hints, sizeof(hints) );
    hints.ai_flags = AI_NUMERICHOST;
    hints.ai_family = AF_UNSPEC;
//    hints.ai_socktype = SOCK_STREAM;
//    hints.ai_protocol = IPPROTO_TCP;


//--------------------------------
// Call getaddrinfo(). If the call succeeds,
// the result variable will hold a linked list
// of addrinfo structures containing response
// information
    dwRetval = getaddrinfo(argv[1], NULL, &hints, &result);
    if ( dwRetval != 0 ) {
        printf("getaddrinfo failed with error: %d\n", dwRetval);
        WSACleanup();
        return 1;
    }

    printf("getaddrinfo returned success\n");
    
    // Retrieve each address and print out the hex bytes
    for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {

        printf("getaddrinfo response %d\n", i++);
        printf("\tFlags: 0x%x\n", ptr->ai_flags);
        printf("\tFamily: ");
        switch (ptr->ai_family) {
            case AF_UNSPEC:
                printf("Unspecified\n");
                break;
            case AF_INET:
                printf("AF_INET (IPv4)\n");
                break;
            case AF_INET6:
                printf("AF_INET6 (IPv6)\n");
                break;
            case AF_NETBIOS:
                printf("AF_NETBIOS (NetBIOS)\n");
                break;
            default:
                printf("Other %ld\n", ptr->ai_family);
                break;
        }
        printf("\tSocket type: ");
        switch (ptr->ai_socktype) {
            case 0:
                printf("Unspecified\n");
                break;
            case SOCK_STREAM:
                printf("SOCK_STREAM (stream)\n");
                break;
            case SOCK_DGRAM:
                printf("SOCK_DGRAM (datagram) \n");
                break;
            case SOCK_RAW:
                printf("SOCK_RAW (raw) \n");
                break;
            case SOCK_RDM:
                printf("SOCK_RDM (reliable message datagram)\n");
                break;
            case SOCK_SEQPACKET:
                printf("SOCK_SEQPACKET (pseudo-stream packet)\n");
                break;
            default:
                printf("Other %ld\n", ptr->ai_socktype);
                break;
        }
        printf("\tProtocol: ");
        switch (ptr->ai_protocol) {
            case 0:
                printf("Unspecified\n");
                break;
            case IPPROTO_TCP:
                printf("IPPROTO_TCP (TCP)\n");
                break;
            case IPPROTO_UDP:
                printf("IPPROTO_UDP (UDP) \n");
                break;
            default:
                printf("Other %ld\n", ptr->ai_protocol);
                break;
        }
        printf("\tLength of this sockaddr: %d\n", ptr->ai_addrlen);
        printf("\tCanonical name: %s\n", ptr->ai_canonname);
    }

    freeaddrinfo(result);
    WSACleanup();

    return 0;
}

Windows 2000 以前のバージョンでの getaddrinfo のサポート

getaddrinfo 関数は、Windows XP 以降で Ws2_32.dll に追加されました。この関数を使用するアプリケーションを以前のバージョンの Windows で実行するには、Ws2tcpip.h および Wspiapi.h ファイルをインクルードする必要があります。Wspiapi.h インクルードファイルを追加すると、getaddrinfo 関数は Wspiapi.h ファイル内の WspiapiGetAddrInfo インライン関数として定義されます。実行時には、Ws2_32.dll または Wship6.dll (Windows 2000 向け IPv6 Technology Preview で getaddrinfo を含むファイル) が getaddrinfo を含まない場合には、Wspiapi.h ヘッダーファイル内のコードに基づいて getaddrinfo のバージョンがインラインで実装されるように、WspiapiGetAddrInfo 関数が実装されます。このインラインコードは、getaddrinfo 関数をネイティブにサポートしない古い Windows プラットフォームで使用されます。

IPv6 プロトコルは、Windows 2000 向け IPv6 Technology Preview がインストールされている場合に Windows 2000 でサポートされます。それ以外の場合、Windows XP より前のバージョンの Windows での getaddrinfo のサポートは、IPv4 名前解決の処理に限定されます。

GetAddrInfoW 関数は getaddrinfo の Unicode 版です。GetAddrInfoW 関数は、Windows XP Service Pack 2 (SP2) で Ws2_32.dll に追加されました。GetAddrInfoW 関数は、Windows XP SP2 より前のバージョンの Windows では使用できません。

Windows Phone 8: この関数は、Windows Phone 8 以降の Windows Phone ストアアプリでサポートされます。

Windows 8.1 および Windows Server 2012 R2: この関数は、Windows 8.1、Windows Server 2012 R2 以降の Windows ストアアプリでサポートされます。

出典・ライセンス: 上記「公式ドキュメント」の内容は Microsoft の Win32 API ドキュメント(MicrosoftDocs/sdk-api)を日本語に翻訳・改変したものです。© Microsoft Corporation. CC BY 4.0 で提供。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)

各言語での呼び出し定義

// WS2_32.dll
#include <windows.h>

INT getaddrinfo(
    LPCSTR pNodeName,   // optional
    LPCSTR pServiceName,   // optional
    const ADDRINFOA* pHints,   // optional
    ADDRINFOA** ppResult
);
[DllImport("WS2_32.dll", SetLastError = true, ExactSpelling = true)]
static extern int getaddrinfo(
    [MarshalAs(UnmanagedType.LPStr)] string pNodeName,   // LPCSTR optional
    [MarshalAs(UnmanagedType.LPStr)] string pServiceName,   // LPCSTR optional
    IntPtr pHints,   // ADDRINFOA* optional
    IntPtr ppResult   // ADDRINFOA** out
);
<DllImport("WS2_32.dll", SetLastError:=True, ExactSpelling:=True)>
Public Shared Function getaddrinfo(
    <MarshalAs(UnmanagedType.LPStr)> pNodeName As String,   ' LPCSTR optional
    <MarshalAs(UnmanagedType.LPStr)> pServiceName As String,   ' LPCSTR optional
    pHints As IntPtr,   ' ADDRINFOA* optional
    ppResult As IntPtr   ' ADDRINFOA** out
) As Integer
End Function
' pNodeName : LPCSTR optional
' pServiceName : LPCSTR optional
' pHints : ADDRINFOA* optional
' ppResult : ADDRINFOA** out
Declare PtrSafe Function getaddrinfo Lib "ws2_32" ( _
    ByVal pNodeName As String, _
    ByVal pServiceName As String, _
    ByVal pHints As LongPtr, _
    ByVal ppResult As LongPtr) As Long
' VBA7前提(PtrSafe)。32bit Office では LongPtr→Long。Integer=16bit / Long=32bit / LongLong=64bit。
import ctypes
from ctypes import wintypes

getaddrinfo = ctypes.windll.ws2_32.getaddrinfo
getaddrinfo.restype = ctypes.c_int
getaddrinfo.argtypes = [
    wintypes.LPCSTR,  # pNodeName : LPCSTR optional
    wintypes.LPCSTR,  # pServiceName : LPCSTR optional
    ctypes.c_void_p,  # pHints : ADDRINFOA* optional
    ctypes.c_void_p,  # ppResult : ADDRINFOA** out
]
# GetLastError: use ctypes.GetLastError() (or ctypes.WinDLL(use_last_error=True))
require 'fiddle'
require 'fiddle/import'

lib = Fiddle.dlopen('WS2_32.dll')
getaddrinfo = Fiddle::Function.new(
  lib['getaddrinfo'],
  [
    Fiddle::TYPE_VOIDP,  # pNodeName : LPCSTR optional
    Fiddle::TYPE_VOIDP,  # pServiceName : LPCSTR optional
    Fiddle::TYPE_VOIDP,  # pHints : ADDRINFOA* optional
    Fiddle::TYPE_VOIDP,  # ppResult : ADDRINFOA** out
  ],
  Fiddle::TYPE_INT)
#[link(name = "ws2_32")]
extern "system" {
    fn getaddrinfo(
        pNodeName: *const u8,  // LPCSTR optional
        pServiceName: *const u8,  // LPCSTR optional
        pHints: *const ADDRINFOA,  // ADDRINFOA* optional
        ppResult: *mut *mut ADDRINFOA  // ADDRINFOA** out
    ) -> i32;
}
// crates: windows-sys provides ready-made bindings for this API.
$sig = @"
[DllImport("WS2_32.dll", SetLastError = true)]
public static extern int getaddrinfo([MarshalAs(UnmanagedType.LPStr)] string pNodeName, [MarshalAs(UnmanagedType.LPStr)] string pServiceName, IntPtr pHints, IntPtr ppResult);
"@
$api = Add-Type -MemberDefinition $sig -Name 'WS2_32_getaddrinfo' -Namespace Win32 -PassThru
# $api::getaddrinfo(pNodeName, pServiceName, pHints, ppResult)
#uselib "WS2_32.dll"
#func global getaddrinfo "getaddrinfo" sptr, sptr, sptr, sptr
; getaddrinfo pNodeName, pServiceName, varptr(pHints), varptr(ppResult)   ; 戻り値は stat
; pNodeName : LPCSTR optional -> "sptr"
; pServiceName : LPCSTR optional -> "sptr"
; pHints : ADDRINFOA* optional -> "sptr"
; ppResult : ADDRINFOA** out -> "sptr"
; ※HSP3.7は #func のため戻り値はシステム変数 stat に格納されます。
出力引数:
#uselib "WS2_32.dll"
#cfunc global getaddrinfo "getaddrinfo" str, str, var, var
; res = getaddrinfo(pNodeName, pServiceName, pHints, ppResult)
; pNodeName : LPCSTR optional -> "str"
; pServiceName : LPCSTR optional -> "str"
; pHints : ADDRINFOA* optional -> "var"
; ppResult : ADDRINFOA** out -> "var"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
出力引数:
; INT getaddrinfo(LPCSTR pNodeName, LPCSTR pServiceName, ADDRINFOA* pHints, ADDRINFOA** ppResult)
#uselib "WS2_32.dll"
#cfunc global getaddrinfo "getaddrinfo" str, str, var, var
; res = getaddrinfo(pNodeName, pServiceName, pHints, ppResult)
; pNodeName : LPCSTR optional -> "str"
; pServiceName : LPCSTR optional -> "str"
; pHints : ADDRINFOA* optional -> "var"
; ppResult : ADDRINFOA** out -> "var"
; ※出力/バッファ引数は var 方式(変数を直接渡す)。varptr 方式にも切替可。
import (
	"golang.org/x/sys/windows"
	"unsafe"
)

var (
	ws2_32 = windows.NewLazySystemDLL("WS2_32.dll")
	procgetaddrinfo = ws2_32.NewProc("getaddrinfo")
)

// pNodeName (LPCSTR optional), pServiceName (LPCSTR optional), pHints (ADDRINFOA* optional), ppResult (ADDRINFOA** out)
r1, _, err := procgetaddrinfo.Call(
	uintptr(unsafe.Pointer(windows.BytePtrFromString(pNodeName))),
	uintptr(unsafe.Pointer(windows.BytePtrFromString(pServiceName))),
	uintptr(pHints),
	uintptr(ppResult),
)
_ = err  // syscall.Errno (valid when the call sets last-error)
_ = r1   // INT
function getaddrinfo(
  pNodeName: PAnsiChar;   // LPCSTR optional
  pServiceName: PAnsiChar;   // LPCSTR optional
  pHints: Pointer;   // ADDRINFOA* optional
  ppResult: Pointer   // ADDRINFOA** out
): Integer; stdcall;
  external 'WS2_32.dll' name 'getaddrinfo';
result := DllCall("WS2_32\getaddrinfo"
    , "AStr", pNodeName   ; LPCSTR optional
    , "AStr", pServiceName   ; LPCSTR optional
    , "Ptr", pHints   ; ADDRINFOA* optional
    , "Ptr", ppResult   ; ADDRINFOA** out
    , "Int")   ; return: INT
●getaddrinfo(pNodeName, pServiceName, pHints, ppResult) = DLL("WS2_32.dll", "int getaddrinfo(char*, char*, void*, void*)")
# 呼び出し: getaddrinfo(pNodeName, pServiceName, pHints, ppResult)
# pNodeName : LPCSTR optional -> "char*"
# pServiceName : LPCSTR optional -> "char*"
# pHints : ADDRINFOA* optional -> "void*"
# ppResult : ADDRINFOA** out -> "void*"
# なでしこ1は32bit・ANSI(Shift_JIS)。文字列=char*(ANSI)、ポインタ/ハンドル=void*(4byte)。
const std = @import("std");

extern "ws2_32" fn getaddrinfo(
    pNodeName: [*c]const u8, // LPCSTR optional
    pServiceName: [*c]const u8, // LPCSTR optional
    pHints: [*c]ADDRINFOA, // ADDRINFOA* optional
    ppResult: [*c][*c]ADDRINFOA // ADDRINFOA** out
) callconv(std.os.windows.WINAPI) i32;
proc getaddrinfo(
    pNodeName: cstring,  # LPCSTR optional
    pServiceName: cstring,  # LPCSTR optional
    pHints: ptr ADDRINFOA,  # ADDRINFOA* optional
    ppResult: ptr ADDRINFOA  # ADDRINFOA** out
): int32 {.importc: "getaddrinfo", stdcall, dynlib: "WS2_32.dll".}
pragma(lib, "ws2_32");
extern(Windows)
int getaddrinfo(
    const(char)* pNodeName,   // LPCSTR optional
    const(char)* pServiceName,   // LPCSTR optional
    ADDRINFOA* pHints,   // ADDRINFOA* optional
    ADDRINFOA** ppResult   // ADDRINFOA** out
);
ccall((:getaddrinfo, "WS2_32.dll"), stdcall, Int32,
      (Cstring, Cstring, Ptr{ADDRINFOA}, Ptr{ADDRINFOA}),
      pNodeName, pServiceName, pHints, ppResult)
# pNodeName : LPCSTR optional -> Cstring
# pServiceName : LPCSTR optional -> Cstring
# pHints : ADDRINFOA* optional -> Ptr{ADDRINFOA}
# ppResult : ADDRINFOA** out -> Ptr{ADDRINFOA}
# stdcall は 32bit のみ意味を持つ(x64 では無視)。
local ffi = require("ffi")
ffi.cdef[[
int32_t getaddrinfo(
    const char* pNodeName,
    const char* pServiceName,
    void* pHints,
    void* ppResult);
]]
local ws2_32 = ffi.load("ws2_32")
-- ws2_32.getaddrinfo(pNodeName, pServiceName, pHints, ppResult)
-- pNodeName : LPCSTR optional
-- pServiceName : LPCSTR optional
-- pHints : ADDRINFOA* optional
-- ppResult : ADDRINFOA** out
-- 構造体/GUIDへのポインタは cdef が通るよう void* で表記(実型は各引数コメント参照)。値渡し構造体・enum は対応する typedef を cdef に追加すること。
const koffi = require('koffi');
const lib = koffi.load('WS2_32.dll');
const getaddrinfo = lib.func('__stdcall', 'getaddrinfo', 'int32_t', ['str', 'str', 'void *', 'void *']);
// getaddrinfo(pNodeName, pServiceName, pHints, ppResult)
// pNodeName : LPCSTR optional -> 'str'
// pServiceName : LPCSTR optional -> 'str'
// pHints : ADDRINFOA* optional -> 'void *'
// ppResult : ADDRINFOA** out -> 'void *'
// 出力ポインタは koffi.out(...) で包む。構造体は koffi.struct で定義。
const lib = Deno.dlopen("WS2_32.dll", {
  getaddrinfo: { parameters: ["buffer", "buffer", "pointer", "pointer"], result: "i32" },
});
// lib.symbols.getaddrinfo(pNodeName, pServiceName, pHints, ppResult)
// pNodeName : LPCSTR optional -> "buffer"
// pServiceName : LPCSTR optional -> "buffer"
// pHints : ADDRINFOA* optional -> "pointer"
// ppResult : ADDRINFOA** out -> "pointer"
// 文字列引数は "buffer"(NUL 終端のバイト列を Uint8Array で渡す)。
// 値渡し構造体は { struct: [ ...field types... ] } を使用。
<?php
$ffi = FFI::cdef(<<<C
int32_t getaddrinfo(
    const char* pNodeName,
    const char* pServiceName,
    void* pHints,
    void* ppResult);
C, "WS2_32.dll");
// $ffi->getaddrinfo(pNodeName, pServiceName, pHints, ppResult);
// pNodeName : LPCSTR optional
// pServiceName : LPCSTR optional
// pHints : ADDRINFOA* optional
// ppResult : ADDRINFOA** out
// 構造体/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 getaddrinfo(
        String pNodeName,   // LPCSTR optional
        String pServiceName,   // LPCSTR optional
        Pointer pHints,   // ADDRINFOA* optional
        Pointer ppResult   // ADDRINFOA** out
    );
}
@[Link("ws2_32")]
lib LibWS2_32
  fun getaddrinfo = getaddrinfo(
    pNodeName : UInt8*,   # LPCSTR optional
    pServiceName : UInt8*,   # LPCSTR optional
    pHints : ADDRINFOA*,   # ADDRINFOA* optional
    ppResult : ADDRINFOA**   # ADDRINFOA** out
  ) : Int32
end
# 構造体/GUID/enum は lib 内に対応する型定義が必要。
# 呼出規約: x64 は規約統一のため OK。x86(32bit)は WINAPI=stdcall だが Crystal の fun に stdcall 付与構文がなく非対応。
import 'dart:ffi';
import 'package:ffi/ffi.dart';

typedef getaddrinfoNative = Int32 Function(Pointer<Utf8>, Pointer<Utf8>, Pointer<Void>, Pointer<Void>);
typedef getaddrinfoDart = int Function(Pointer<Utf8>, Pointer<Utf8>, Pointer<Void>, Pointer<Void>);
final getaddrinfo = DynamicLibrary.open('WS2_32.dll')
    .lookupFunction<getaddrinfoNative, getaddrinfoDart>('getaddrinfo');
// pNodeName : LPCSTR optional -> Pointer<Utf8>
// pServiceName : LPCSTR optional -> Pointer<Utf8>
// pHints : ADDRINFOA* optional -> Pointer<Void>
// ppResult : ADDRINFOA** out -> Pointer<Void>
// 文字列は package:ffi の "...".toNativeUtf16()/toNativeUtf8() で変換。
{$mode objfpc}{$H+}
function getaddrinfo(
  pNodeName: PAnsiChar;   // LPCSTR optional
  pServiceName: PAnsiChar;   // LPCSTR optional
  pHints: Pointer;   // ADDRINFOA* optional
  ppResult: Pointer   // ADDRINFOA** out
): Integer; stdcall;
  external 'WS2_32.dll' name 'getaddrinfo';
import Foreign
import Foreign.C.Types
import Foreign.C.String

foreign import stdcall safe "getaddrinfo"
  c_getaddrinfo :: CString -> CString -> Ptr () -> Ptr () -> IO Int32
-- pNodeName : LPCSTR optional -> CString
-- pServiceName : LPCSTR optional -> CString
-- pHints : ADDRINFOA* optional -> Ptr ()
-- ppResult : ADDRINFOA** out -> Ptr ()
-- 要 GHC(Windows)。stdcall は x64 では ccall として扱われる。ブロックする API は safe 呼び出し推奨。
open Ctypes
open Foreign

let getaddrinfo =
  foreign "getaddrinfo"
    (string @-> string @-> (ptr void) @-> (ptr void) @-> returning int32_t)
(* pNodeName : LPCSTR optional -> string *)
(* pServiceName : LPCSTR optional -> string *)
(* pHints : ADDRINFOA* optional -> (ptr void) *)
(* ppResult : ADDRINFOA** out -> (ptr void) *)
(* 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 ("getaddrinfo" getaddrinfo :convention :stdcall) :int32
  (p-node-name :string)   ; LPCSTR optional
  (p-service-name :string)   ; LPCSTR optional
  (p-hints :pointer)   ; ADDRINFOA* optional
  (pp-result :pointer))   ; ADDRINFOA** out
; isize/usize(INT_PTR/SIZE_T)は x64 前提で :int64/:uint64。x86 では :int32/:uint32。
use Win32::API;
my $getaddrinfo = Win32::API::More->new('WS2_32',
    'int getaddrinfo(LPCSTR pNodeName, LPCSTR pServiceName, LPVOID pHints, LPVOID ppResult)');
# my $ret = $getaddrinfo->Call($pNodeName, $pServiceName, $pHints, $ppResult);
# pNodeName : LPCSTR optional -> LPCSTR
# pServiceName : LPCSTR optional -> LPCSTR
# pHints : ADDRINFOA* optional -> LPVOID
# ppResult : ADDRINFOA** out -> LPVOID
# 値渡し構造体は pack() した文字列、または Win32::API::Struct を使用。

関連項目

公式の関連項目
使用する型