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. stdafx用于在 VC++中实现预编译头文件。您可以将您的库头文件(如 windows.h 和 winsock.h 等)放在那里,并且每次修改 stdafx.h 时它们只会编译一次。

  2. APIENTRY 通常只是 __stdcall 的定义,但有时它定义为空白(例如,如果不支持 __stdcall)。这是为了使您的代码更具可移植性。

  3. 如果没有您遇到的实际错误,我将无能为力。但我的第一个猜测是你的构建中有 unicode,它抱怨 MessageBoxW 不接受 char[100] 作为参数。在这种情况下,要么在任何地方使用宽字符,要么关闭 unicode,或者使用 MessageBoxA 显式使用 ASCII 版本。

编辑:

现在有了错误,这很容易。在项目属性 -> 链接器 -> 输入 -> 附加依赖项下,添加 ws2_32.lib。所以你可以得到链接的 Winsock 函数。

缺少的 _main 表示您正在将应用程序构建为控制台应用程序,而不是 Windows 应用程序。返回项目属性 -> 链接器 -> 系统并将子系统设置为 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 库。您可以通过两种方式做到这一点:

  1. 将其添加到项目属性 -> 链接器 -> 输入 -> “其他库”中(不要忘记为调试和发布配置执行此操作)。
  2. 在你的头文件中添加这个编译器指令:

    #pragma 注释(lib,“ws2_32.lib”)

我更喜欢第二种方法,因为您所做的更改在源代码中可见,而不是隐藏在项目选项的深处。

至于 APIENTRY 和类似的定义——它只是一种方便,比如返回 NULL 而不是 0 来指出你没有返回任何东西而不是数字零。使代码更易于阅读和理解。

于 2009-03-21T17:56:36.933 回答
0

stdafx 与 Visual Studio 中的预编译头文件有关。它与套接字没有任何特定关系。

APIENTRY 与 WinMain 的调用约定有关,同样它不应该与套接字有任何关系。

发布错误。

于 2009-03-21T17:36:57.137 回答
0

尝试下一个
打开项目属性,选择链接器属性,选择输入子项在附加依赖项中添加 Ws2_32.lib 不要忘记对所有项目配置执行相同的操作。
看来你也需要改变使用 int main() 而不是 WinMain(...)

stdafx.h - 通常意味着预编译的头文件 VC++ 项目
APIENTRY - 调用约定。在您的情况下,它是 __stdcall,但有时可能意味着其他。

于 2009-03-21T17:53:10.233 回答
0

就链接器错误而言,您应该链接到 wsock32.lib。

于 2009-03-21T17:57:23.703 回答
0

如果链接器抱怨它找不到 _main,这意味着它正在尝试将您的程序链接为控制台应用程序,这意味着您应该定义 main() 而不是 WinMain()。如果您有 WinMain(),您可能应该将您的应用程序构建为 Windows 应用程序。

于 2009-03-21T17:57:53.217 回答