views:

661

answers:

6
#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;
}

This program is for getting information of available wsock version in the computer. I cannot understand why "stdafx.h" is included in program. What's the significance of APIENTRY? Can't we use _stdcall instead? I also can't compile it in VC++. What's the problem with the code?

Below are the errors when executing program there are no errors during compiling.

--------------------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)
+8  A: 
  1. stdafx is used to implement precompiled headers in VC++. You can put your library headers like windows.h and winsock.h, etc.. in there and they will only be compiled once each time you modify stdafx.h.

  2. APIENTRY is usually just a define for __stdcall, but sometimes it is defined blank (if __stdcall is not supported for example). It's to make your code more portable.

  3. Without the actual errors you are getting, I'm not going to be able to help much. But my first guess is that you have unicode on in your build and it's complaining that MessageBoxW doesn't take a char[100] as an argument. In this case, either use wide chars everywhere, or turn off unicode, or use MessageBoxA to explicitly use the ASCII version.

Edit:

Now with the errors, it's easy. Under Project properties -> Linker -> Input -> Additional Dependencies, add ws2_32.lib. So you can get the Winsock functions linked in.

The missing _main indicates that you are building the app as a console app, and not a windows app. Go back to project Properties -> Linker -> System and set SubSystem to Windows (/Subsystem:Windows) instead of Console. Or else, just rename WinMain to int main() (Make sure you drop the APIENTRY).

Also, if you're using MSVC++ you might as well use the safer sprintf_s:

sprintf_s(buf,100,"%d.%d",HIBYTE(ws.wVersion),LOBYTE(ws.wVersion));
Eclipse
Beat me to it. That's what I was going to say. :)
Sam Hoice
still i'm getting this error--------------------Configuration: sa - Win32 Debug--------------------Linking...LINK : fatal error LNK1104: cannot open file "odbccp32.libwin32.lib"Error executing link.exe.sa.exe - 1 error(s), 0 warning(s)
paragjain
Somewhere in your options you've deleted a semi-colon between odbccp32.lib and win32.lib
Eclipse
You might be best off starting a new project without any of the changes you've made so far.
Eclipse
there is a . in between odbccp32.lib and win32.lib in project settings link tab and object/libraru modules
paragjain
Use a space instead (I was wrong about the semi-colon)
Eclipse
A: 

stdafx has to do with precompiled headers in visual studio. It doesn't have anything specific to do with the socket.

APIENTRY has to do with the calling convention of WinMain, again it shouldn't have anything to do with the socket.

Post errors.

Sam Hoice
A: 

try next
open project properties, select linker properties, select Input subitem add Ws2_32.lib in additional dependecies item don't forget do the same for all project configurations.
also it seems you need change use int main() instead WinMain(...)

stdafx.h - usualy means precompiled header VC++ projects
APIENTRY - calling convention. in your case it is __stdcall, but sometimes could mean sometihng other.

bb
+4  A: 

As for the errors: you need to link against ws2_32.lib library. You can do this in two ways:

  1. Add it in Project properties -> Linker -> Input -> "additional libraries" (don't forget to do this for both Debug and Release configurations).
  2. In your header add this compiler directive:

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

I prefer the second method because the changes you make are visible in the source instead of being hidden deep in project options.

As for APIENTRY and similar defines - it's merely a convenience like returning NULL instead of 0 to point out that you're returning nothing instead of a number zero. Makes code easier to read and understand.

frgtn
A: 

As far as the linker errors are concerned you should link to wsock32.lib.

Naveen
A: 

If the linker complains that it can't find _main, it means that it is trying to link your program as a console-application, which means that you should define main() and not WinMain(). If you have WinMain(), you should probably be building your application as a Windows application.

JesperE