这个 MSVC++ 编译错误是啥意思

Posted

技术标签:

【中文标题】这个 MSVC++ 编译错误是啥意思【英文标题】:What does this MSVC++ compile error mean这个 MSVC++ 编译错误是什么意思 【发布时间】:2011-06-12 05:57:06 【问题描述】:

我有这个编译错误,我不明白出了什么问题。我的 Microsoft Visual Studio 项目是 Win32 项目(不是控制台):

1>MSVCRT.lib(crtexew.obj) : error LNK2001: unresolved external symbol _WinMain@16
1>C:\Users\Soribo\Desktop\C++ Programming\Visual C++ Programming\KeyboardHook\Release\KeyboardHook.exe : fatal error LNK1120: 1 unresolved externals

编辑:将#include "stdafx.h" 作为第一行后,编译错误是:

1>MSVCRT.lib(crtexew.obj) : error LNK2001: unresolved external symbol _WinMain@16
1>C:\Users\Soribo\Desktop\C++ Programming\Visual C++ Programming\KeyboardHook\Release\KeyboardHook.exe : fatal error LNK1120: 1 unresolved externals

编辑:嗯,我已经定义了 WinMain 函数不是吗?见以下代码:

/*
  Application: 
*/

#include <windows.h>
#include <cstdlib>
#include "stdafx.h"

using namespace std;

static HHOOK     keyboardHook;
static HINSTANCE gInstance;


// Functions List //
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK LowLevelKeyboardProc( int nCode, WPARAM wParam, LPARAM lParam );
HHook ActivateKeyboardHook( HookProc hookProc, HINSTANCE hInstance );
bool DeactivateKeyboardHook( HHook keyboardHook );


int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
//int WINAPI WinMain( HINSTANCE gInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )

    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;

    //Step 1: Registering the Window Class
    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.style         = 0;
    wc.lpfnWndProc   = WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = gInstance;
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(DKGRAY_BRUSH);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = L"Custom Class";
    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

    // if registration of main class fails
    if(!RegisterClassEx(&wc))
    
        MessageBox(NULL, L"Window Registration Failed!", L"Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    

    // Step 2: Creating the Window
    hwnd = CreateWindowEx(
        WS_EX_CLIENTEDGE,
        L"Custom Class",
        L"App Name",
        WS_CAPTION|WS_MINIMIZEBOX|WS_VISIBLE|WS_OVERLAPPED|WS_SYSMENU,
        CW_USEDEFAULT, CW_USEDEFAULT, 600, 500,
        NULL, NULL, gInstance, NULL);

    if(hwnd == NULL)
    
        MessageBox(NULL, L"Window Creation Failed!", L"Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    // Step 3: The Message Loop
    while(GetMessage(&Msg, NULL, 0, 0) > 0)
    
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    
    return Msg.wParam;


LRESULT CALLBACK LowLevelKeyboardProc( int nCode, WPARAM wParam, LPARAM lParam )

    /*if ( code < 0 )
    
        return CallNextHookEx( NULL, code, wParam, lParam );
    */  

    switch ( wParam )
    
        case WM_KEYDOWN:
        
            MessageBox( NULL, L"Notify", L"Key Down", MB_OK );        
        
        break;
        case WM_KEYUP:
        
            MessageBox( NULL, L"Notify", L"Key Up", MB_OK );                        
        
        break;
        case WM_SYSKEYDOWN:
        
            MessageBox( NULL, L"Notify", L"Sys Key Down", MB_OK );                        
        
        break;
        case WM_SYSKEYUP:
        
            MessageBox( NULL, L"Notify", L"Sys Key Up", MB_OK );                        
        
        break;
        default:
        
         
        break;
    

    return CallNextHookEx( NULL, nCode, wParam, lParam );


LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)


    switch(msg)
    
        case WM_CREATE:
                          
             keyboardHook = ActivateKeyboardHook( &LowLevelKeyboardProc, gInstance );
            
        break;
        case WM_COMMAND:
        
             switch(LOWORD(wParam)) 
             

                  default:
                  break;
             
        
        break;
        case WM_CLOSE:
        
            DeactivateKeyboardHook( keyboardHook );
            DestroyWindow(hwnd);
        
        break;
        case WM_DESTROY:
            PostQuitMessage(0);
        break;
        default: 
        break;
    

    return DefWindowProc(hwnd, msg, wParam, lParam);


HHOOK ActivateKeyboardHook( HookProc hookProc, HINSTANCE hInstance )

     return SetWindowsHookEx( WH_KEYBOARD_LL, hookProc, hInstance, 0 );


bool DeactivateKeyboardHook( HHook keyboardHook )

     return UnhookWindowsHookEx( keyboardHook );

【问题讨论】:

【参考方案1】:

那不是编译错误,那是链接器错误,说明你的程序没有定义WinMain函数,这是程序的入口。

确保你的程序有这个功能:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow);

请参阅此 MSDN 文档:

WinMain: The Application Entry Point
#include <windows.h>
#include <cstdlib>
#include "stdafx.h"

如果你选择了预编译的头文件,那么上面的错误,stdafx.h应该包含在文件的开头。所以把顺序改成:

#include "stdafx.h"  //this should be first line of the program!
#include <windows.h>
#include <cstdlib>

我认为您不需要包含&lt;windows.h&gt;,因为stdafx.h 很可能已经包含它。看看吧。

现在为什么要先包含它?因为预编译头,顾名思义,是一个 precompiled 头。编译器不会每次都编译它。相反,它会将其中的所有内容编译一次。如果你不先包含它,编译器将不知道是否编译它之前包含的文件,因为可能那些文件已经包含在stdafx.h中,所以已经编译了。请参阅此主题:

include stdafx.h in header or source file?(在 *** 上) Use Precompiled Header File(在 MSDN)

【讨论】:

@Nawaz 非常感谢您的帮助。为什么它需要在 MVS 中排名第一?编辑:进行这些更改后,它仍然给出相同的编译器错误? @user593747:你先包含它了吗?它解决了吗?如果没有,请发布所有错误消息! 如果您在 StdAfx.h 之前包含其他标头,那么这可能会改变 StdAfx.h 的含义。这样就无法预编译标头。 @user: 1. 一般称为MSVC++,因为IDE不是为你编译的,编译器才是。 :) 2. 因为这就是预编译头文件的工作原理。 @user:因为当预编译头文件被启用时(默认情况下),编译器首先搜索#include "stdafx.h",忽略路上的一切。【参考方案2】:

这不是编译错误,而是链接错误。基本上,您使用的是在某处声明但从未在任何翻译单元中定义的函数。

【讨论】:

以上是关于这个 MSVC++ 编译错误是啥意思的主要内容,如果未能解决你的问题,请参考以下文章

MS VC++ 2010的这个链接器错误是啥意思[重复]

flash里的编译器错误是啥意思啊?

Boost Spirit v2 gcc 编译错误,使用 msvc 未显示

编译时错误“架构 x86_64 的未定义符号”是啥意思?

“_OBJC_CLASS_$_CATransaction,引用自:”编译时错误是啥意思?

MSVC++ 的属性选项卡上的 Items 是啥意思?