スポンサーリンク

C++からwin32apiでWinMainを使うmeson.buildを書いてみる

WinMainを使う場合、/SUBSYSTEM:WINDOWSを指定する。

問題は、mesonが勝手に/SUBSYSTEM:CONSOLEをつけてしまうので、エントリポイントがmainなのかWinMainなのかわからなくなりエラーが出る。

[1/1] Linking target myapp.exe
FAILED: myapp.exe myapp.pdb
"link" /MACHINE:x64 /OUT:myapp.exe myapp.exe.p/main.cpp.obj "/nologo" "/release" "/nologo" "/DEBUG" "/PDB:myapp.pdb" "/SUBSYSTEM:WINDOWS" "/SUBSYSTEM:CONSOLE" "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "comdlg32.lib" "advapi32.lib"
MSVCRTD.lib(exe_main.obj) : error LNK2019: 未解決の外部シンボル main が関数 "int __cdecl invoke_main(void)" (?invoke_main@@YAHXZ) で参照されました
myapp.exe : fatal error LNK1120: 1 件の未解決の外部参照
ninja: build stopped: subcommand failed.

これを回避するために、 gui_app: true を指定する。

project('myapp', 'cpp') cpp = meson.get_compiler('cpp') executable('myapp', 'main.cpp', gui_app: true, # WinMainを使うときはこれが必要 cpp_args: [ '/D_WINDOWS' ], link_args: [ '/SUBSYSTEM:WINDOWS' # WinMainを使うときはこれが必要 ] )

ビルド

meson setup build

meson compile -C build

の順で実行する。

	

(mesonenv) C:\Users\myuser\source\repos\win32>meson setup build Directory already configured. Just run your build command (e.g. ninja) and Meson will regenerate as necessary. If ninja fails, run "ninja reconfigure" or "meson setup --reconfigure" to force Meson to regenerate. If build failures persist, run "meson setup --wipe" to rebuild from scratch using the same options as passed when configuring the build. To change option values, run "meson configure" instead. (mesonenv) C:\Users\myuser\source\repos\win32>meson compile -C build Activating VS 17.5.4 INFO: automatically activated MSVC compiler environment INFO: autodetecting backend as ninja INFO: calculating backend command to run: C:\Users\myuser\anaconda3\envs\mesonenv\Library\bin\ninja.EXE -C C:/Users/szl/source/repos/win32/build ninja: Entering directory `C:/Users/myuser/source/repos/win32/build' [0/1] Regenerating build files. The Meson build system Version: 1.0.1 Source dir: C:\Users\myuser\source\repos\win32 Build dir: C:\Users\myuser\source\repos\win32\build Build type: native build Project name: myapp Project version: undefined C++ compiler for the host machine: cl (msvc 19.35.32217.1 "Microsoft(R) C/C++ Optimizing Compiler Version 19.35.32217.1 for x64") C++ linker for the host machine: link link 14.35.32217.1 Host machine cpu family: x86_64 Host machine cpu: x86_64 Build targets in project: 1 Found ninja-1.10.2 at C:\Users\myuser\anaconda3\envs\mesonenv\Library\bin\ninja.EXE Cleaning... 0 files. [1/1] Linking target myapp.exe

サンプルコード main.cpp

#include<windows.h>

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
  HDC hdc;
  switch (msg) {
  case WM_DESTROY:
    PostQuitMessage(0);
    return 0;
  }
  return DefWindowProc(hwnd, msg, wp, lp);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  PSTR lpCmdLine, int nCmdShow) {
  HWND hwnd;
  WNDCLASS winc;
  MSG msg;

  winc.style = CS_HREDRAW | CS_VREDRAW;
  winc.lpfnWndProc = WndProc;
  winc.cbClsExtra = winc.cbWndExtra = 0;
  winc.hInstance = hInstance;
  winc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  winc.hCursor = LoadCursor(NULL, IDC_ARROW);
  winc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  winc.lpszMenuName = NULL;
  winc.lpszClassName = TEXT("SZL-WIN");

  if (!RegisterClass(&winc)) return 0;

  hwnd = CreateWindow(
    TEXT("SZL-WIN"), TEXT("test"),
    WS_OVERLAPPEDWINDOW | WS_VISIBLE,
    CW_USEDEFAULT, CW_USEDEFAULT,
    CW_USEDEFAULT, CW_USEDEFAULT,
    NULL, NULL,
    hInstance, NULL
  );

  if (hwnd == NULL) return 0;

  while (GetMessage(&msg, NULL, 0, 0)) DispatchMessage(&msg);
  return msg.wParam;
}

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: