簡體   English   中英

在沒有Windows.h的WIN32上編譯

[英]Compile on WIN32 without Windows.h

作為學習練習,我編寫了一個標准Windows程序,該程序注冊並創建一個窗口,但未明確包含Windows.h Windows.h所有標頭符號均已被提取並放入自定義標頭中,我將其包含在源代碼中。 自定義標頭具有類型定義,例如CreateWindowWNDCLASSEX

該程序使用cl.exe和如下命令行進行編譯:

cl main.cpp /link opengl32.lib gdi32.lib kernel32.lib user32.lib

據我了解,這些.lib文件是導入庫,它們可以進行設置工作,以便在進程啟動時從關聯的DLL加載函數地址。 如果main.cpp直接包含Windows.h則上面的命令行將完全正常工作。 但是,即使在命令行中指定了關聯的導入庫, cl.exe包含自定義標頭后, cl.exe無法將所有函數調用鏈接到Windows API中(未解決的外部符號錯誤)。

是否有某種特殊情況下的魔術cl.exe專為Windows.h執行? 在這種情況下,需要什么步驟來確保正確的鏈接?

這是我可以構造的最小示例:

typedef unsigned __int64 UINT_PTR, *PUINT_PTR;
typedef __int64 LONG_PTR, *PLONG_PTR;
typedef UINT_PTR            WPARAM;
typedef LONG_PTR            LPARAM;
typedef LONG_PTR            LRESULT;
typedef int                 INT;
typedef unsigned int        UINT;
typedef char CHAR;
typedef unsigned short      WORD;
#define CONST const
#define DECLARE_HANDLE(name) struct name##__{int unused;}; typedef struct name##__ *name
DECLARE_HANDLE(HWND);
DECLARE_HANDLE(HINSTANCE);
DECLARE_HANDLE(HICON);
DECLARE_HANDLE(HCURSOR);
DECLARE_HANDLE(HBRUSH);
DECLARE_HANDLE(HMODULE);
typedef unsigned __int64 ULONG_PTR, *PULONG_PTR;
typedef CHAR *NPSTR, *LPSTR, *PSTR;
typedef CONST CHAR *LPCSTR, *PCSTR;
#define CALLBACK    __stdcall
#define WINAPI      __stdcall
typedef LRESULT (CALLBACK* WNDPROC)(HWND, UINT, WPARAM, LPARAM);
#define DECLSPEC_IMPORT __declspec(dllimport)
#define WINUSERAPI DECLSPEC_IMPORT
#define WINBASEAPI DECLSPEC_IMPORT
#define CS_VREDRAW          0x0001
#define CS_HREDRAW          0x0002
#define CS_OWNDC            0x0020
#define MAKEINTRESOURCEA(i) ((LPSTR)((ULONG_PTR)((WORD)(i))))
#define MAKEINTRESOURCE  MAKEINTRESOURCEA
#define IDC_ARROW           MAKEINTRESOURCE(32512)
#define NULL 0
typedef WORD                ATOM;   //BUGBUG - might want to remove this from minwin

typedef struct tagWNDCLASSEXA {
    UINT        cbSize;
    /* Win 3.x */
    UINT        style;
    WNDPROC     lpfnWndProc;
    int         cbClsExtra;
    int         cbWndExtra;
    HINSTANCE   hInstance;
    HICON       hIcon;
    HCURSOR     hCursor;
    HBRUSH      hbrBackground;
    LPCSTR      lpszMenuName;
    LPCSTR      lpszClassName;
    /* Win 4.0 */
    HICON       hIconSm;
} WNDCLASSEXA, *PWNDCLASSEXA, *NPWNDCLASSEXA, *LPWNDCLASSEXA;

WINUSERAPI LRESULT CALLBACK DefWindowProcA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
WINBASEAPI HMODULE WINAPI GetModuleHandleA(LPCSTR lpModuleName);
WINUSERAPI HCURSOR WINAPI LoadCursorA(HINSTANCE hInstance, LPCSTR lpCursorName);
WINUSERAPI ATOM WINAPI RegisterClassExA(CONST WNDCLASSEXA *);

LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
    return DefWindowProcA( hWnd, message, wParam, lParam );
}

INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, INT sw )
{
    // register window class
    WNDCLASSEXA wcex = { 0 };
    wcex.cbSize            = sizeof( WNDCLASSEXA );
    wcex.style            = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    wcex.lpfnWndProc    = WndProc;
    wcex.hInstance        = (HINSTANCE)GetModuleHandleA( NULL );
    wcex.hIcon            = NULL;
    wcex.hCursor        = LoadCursorA( NULL, IDC_ARROW );
    wcex.lpszClassName    = "Title";
    RegisterClassExA( &wcex );

    return 0;
}

編譯:

@echo off
call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x64

set CONSOLE= -subsystem:windows
set CFLAGS= -Zi -nologo
set CFLAGS= -D__WINDOWS__ -D_CRT_SECURE_NO_WARNINGS %CFLAGS%
set LFLAGS= -incremental:no -opt:ref
set LFLAGS= user32.lib kernel32.lib %LFLAGS%

cl %CFLAGS% main.cpp -Fegame.exe /link %LFLAGS% %CONSOLE%

不,這些工具沒有任何作用,尤其是對於Windows.h。

我猜你把標題弄錯了。 在沒有看到標題的情況下很難猜測可能是什么問題,但是仍然存在一種可能性。

對於大多數功能,Windows都有“ ANSI”和“ Wide”兩個版本,因此您看到的CreateWindow實際上是兩個函數CreateWindowACreateWindowW CreateWindow僅作為映射到*A*W名稱的宏存在,這取決於是否定義了UNICODE

因此,如果您為名為CreateWindow的函數提供了原型/聲明,則不會鏈接-庫中存在的是CreateWindowACreateWindowW ,而不是CreateWindow

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM