简体   繁体   中英

Windows.h in Clang c++20 modules

I started working on my first project using c++20 modules, and i chose LLVM Clang as toolset for building. Problem is that, when i try to include windows.h file, clangs acts as if i didn't. (This happens ONLY if i have import in the same translation unit)

module;

#include <windows.h>

export module SomeModule;

import Whatever;

export HWND Something(){...}

In this case, whatever uses Windows.h functionality, throws errors, that symbols do not exist. Example:

error: missing '#include <windef.h>'; 'HWND' must be declared before it is used
    HWND hwnd;
    ^
C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\shared\windef.h:39:28: note: declaration here is not visible
DECLARE_HANDLE            (HWND);

Why? How to make it work? Help please. Thanks in advance!

I was recently able to build a Windows C++20 module, for Visual Studio 2022 17.5 (I didn't check any other compiler), that can be imported in our company code base. In all C++ source files needing Windows API, I then put import Windows; instead of the traditional #include <Windows.h> . Note that this approach requires to use the full names of API functions like CreateFileW , not the traditional macro version CreateFile , since in modules macros are never exported. I see this as an advantage, not polluting the client code with hidden macro definitions that can sometimes create weird compilation errors.

The module definition is a bit of a hack, but seems to work. Here is an abbreviated version, but you get the idea:

module;

#include <string.h>
#include <stdio.h>
#define static // I know it is UB, but it works...

export module Windows;
#pragma warning(disable: 5244)
export
{
#define MICROSOFT_WINDOWS_WINBASE_H_DEFINE_INTERLOCKED_CPLUSPLUS_OVERLOADS 0
    // Windows declarations here
#include <winsock2.h>
#include <windows.h>
}
#include "Windows.macro.h"

The undefined behavior #define static was necessary because in some places of Windows API, some C functions are exported as __inline static , and this is not compatible with export .

The Windows.macro.h header is a generated file from a simple list of macro names to export in a text file. I did not export all macro names (there are tons of them), but only the ones we actually use. The header looks like that:

const auto TEMP_MB_ABORTRETRYIGNORE = MB_ABORTRETRYIGNORE;
#undef MB_ABORTRETRYIGNORE
export const auto MB_ABORTRETRYIGNORE = TEMP_MB_ABORTRETRYIGNORE;

const auto TEMP_MB_ICONSTOP = MB_ICONSTOP;
#undef MB_ICONSTOP
export const auto MB_ICONSTOP = TEMP_MB_ICONSTOP;

const auto TEMP_DATE_SHORTDATE = DATE_SHORTDATE;
#undef DATE_SHORTDATE
export const auto DATE_SHORTDATE = TEMP_DATE_SHORTDATE;
...

I asked recently that question about how to export C macro constants to C++ exportable ones.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM