1
#include "stdafx.h"
#include <windows.h>
#include <winsock.h>
#include <stdio.h>

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR IpCmdLine,int nCmdShow)
{
    WSADATA ws;
    char buf[100];

    WSAStartup(0x0101,&ws);

    sprintf(buf,"%d.%d",HIBYTE(ws.wVersion),LOBYTE(ws.wVersion));
    MessageBox(0,buf,"info",0);
    WSACleanup();
    return 0;
}

このプログラムは、コンピューターで使用可能な wsock バージョンの情報を取得するためのものです。「stdafx.h」がプログラムに含まれている理由がわかりません。APIENTRY の意義は何ですか? 代わりに _stdcall を使用できませんか? また、VC++ でコンパイルすることもできません。コードの問題は何ですか?

以下は、プログラムを実行したときのエラーで、コンパイル中にエラーはありません。

--------------------Configuration: sa - Win32 Debug--------------------
Linking...
sa.obj : error LNK2001: unresolved external symbol _WSACleanup@0
sa.obj : error LNK2001: unresolved external symbol _WSAStartup@8
LIBCD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
Debug/sa.exe : fatal error LNK1120: 3 unresolved externals
Error executing link.exe.

sa.exe - 4 error(s), 0 warning(s)
4

6 に答える 6

8
  1. stdafxVC++ でプリコンパイル済みヘッダーを実装するために使用されます。そこに windows.h や winsock.h などのライブラリ ヘッダーを配置すると、stdafx.h を変更するたびに 1 回だけコンパイルされます。

  2. 通常、APIENTRY は __stdcall の単なる定義ですが、空白で定義されることもあります (たとえば、__stdcall がサポートされていない場合)。コードの移植性を高めるためです。

  3. あなたが得ている実際のエラーがなければ、私はあまり役に立ちません。しかし、私の最初の推測では、ビルドで unicode がオンになっていて、MessageBoxW が char[100] を引数として取りません。この場合、どこでもワイド文字を使用するか、Unicode をオフにするか、MessageBoxA を使用して ASCII バージョンを明示的に使用します。

編集:

エラーがあれば、簡単です。[プロジェクト プロパティ] -> [リンカー] -> [入力] -> [追加の依存関係] の下に、ws2_32.lib を追加します。したがって、Winsock 関数をリンクできます。

_main がないことは、アプリを Windows アプリではなく、コンソール アプリとしてビルドしていることを示しています。プロジェクトの [プロパティ] -> [リンカー] -> [システム] に戻り、SubSystem を Console ではなく Windows (/Subsystem:Windows) に設定します。または、WinMain の名前をint main()(必ず APIENTRY を削除してください) に変更します。

また、MSVC++ を使用している場合は、より安全な sprintf_s を使用することもできます。

sprintf_s(buf,100,"%d.%d",HIBYTE(ws.wVersion),LOBYTE(ws.wVersion));
于 2009-03-21T17:26:44.103 に答える
4

エラーに関しては、ws2_32.lib ライブラリにリンクする必要があります。これは、次の 2 つの方法で行うことができます。

  1. プロジェクト プロパティ -> リンカー -> 入力 -> "追加ライブラリ" に追加します (デバッグ構成とリリース構成の両方でこれを行うことを忘れないでください)。
  2. ヘッダーに次のコンパイラ ディレクティブを追加します。

    #pragma comment(lib, "ws2_32.lib")

私は 2 番目の方法を好みます。これは、行った変更がプロジェクト オプションの奥深くに隠されるのではなく、ソースに表示されるためです。

APIENTRY および同様の定義については、数値ゼロの代わりに何も返さないことを示すために、0 の代わりに NULL を返すのと同じように単に便利です。コードを読みやすく理解しやすくします。

于 2009-03-21T17:56:36.933 に答える
0

stdafx は、ビジュアル スタジオのプリコンパイル済みヘッダーと関係があります。ソケットとは特に関係ありません。

APIENTRY は WinMain の呼び出し規約と関係がありますが、ソケットとは関係ありません。

エラーを投稿します。

于 2009-03-21T17:36:57.137 に答える
0

次に
開いているプロジェクト プロパティを試し、リンカー プロパティを選択し、入力サブアイテムを選択して、追加の依存関係アイテムに Ws2_32.lib を追加します。すべてのプロジェクト構成に対して同じことを忘れないでください。
また、WinMain(...) の代わりに int main() を使用するように変更する必要があるようです

stdafx.h - 通常はプリコンパイル済みヘッダー VC++ プロジェクト
APIENTRY - 呼び出し規約を意味します。あなたの場合は __stdcall ですが、他の何かを意味する場合もあります。

于 2009-03-21T17:53:10.233 に答える
0

リンカー エラーに関する限り、wsock32.lib にリンクする必要があります。

于 2009-03-21T17:57:23.703 に答える
0

リンカが _main を見つけられないと文句を言う場合、プログラムをコンソール アプリケーションとしてリンクしようとしていることを意味します。つまり、WinMain() ではなく main() を定義する必要があります。WinMain() がある場合は、アプリケーションを Windows アプリケーションとして構築する必要があります。

于 2009-03-21T17:57:53.217 に答える