#ifndef __LIBUI_COMPILERVER__ #define __LIBUI_COMPILERVER__ // Visual Studio (Microsoft's compilers) // VS2013 is needed for va_copy(). #ifdef _MSC_VER #if _MSC_VER < 1800 #error Visual Studio 2013 or higher is required to build libui. #endif #endif #ifdef __MINGW32__ // Silence warning: base class 'struct IUnknown' has accessible non-virtual destructor // as MinGW does not process COM interfaces correctly #pragma GCC diagnostic ignored "-Wnon-virtual-dtor" #endif /* TODO this should not be necessary, but I don't know here's @bcampbell's original comment: // sanity check - make sure wchar_t is 16 bits (the assumption on windows) // (MinGW-w64 gcc does seem to define a 16bit wchar_t, but you never know. Other windows gcc ports might not) here's what I got when I tried to investigate on irc.oftc.net/#mingw-w64: { [08:45:20] andlabs, the c++ standard requires `wchar_t` to be a distinct type. On Windows you can simply `static_assert(sizeof(wchar_t) == sizeof(unsigned short) && alignof(wchar_t) == alignof(unsigned short), "");` then reinterpret_cast those pointers. [09:22:16] lh_mouse: yes; that was the point of my question =P but whether that static_assert is always true is another question I have, because again, windows embeds the idea of wchar_t being UTF-16 throughout the API, but when I went to look, I found that the clang developers had a very heated debate about it :S [09:22:28] and I couldn't find any concrete information other than the msvc docs [09:23:04] Since Windows 2000 the NT kernel uses UTF-16. [09:23:50] If you don't care about Windows 9x you can just pretend non-UTF-16 APIs didn't exist. [09:24:04] that's not what I meant [09:24:06] Actually long long long ago Windows used UCS2. [09:24:15] I meant whether sizeof(wchar_t) must necessarily equal sizeof(uint16_t) [09:24:18] and likewise for alignof [09:24:27] for all windows compilers [09:24:29] anyway afk [09:24:31] Yes. That is what the ABI says. [09:24:40] is there a source for that I can point at other people [09:24:45] the ABI != on Windows [09:26:00] okay I really need to afk now but I was about to ask what you meant [09:26:06] and by source I meant URL [09:49:18] andlabs: Sent 17 minutes ago: Here is what Microsoft people describe `wchar_t`: https://docs.microsoft.com/en-us/cpp/cpp/char-wchar-t-char16-t-char32-t [09:49:19] andlabs: Sent 17 minutes ago: It is quite guaranteed: 'In the Microsoft compiler, it represents a 16-bit wide character used to store Unicode encoded as UTF-16LE, the native character type on Windows operating systems.' [09:50:08] andlabs, If you build for cygwin then `wchar_t` is probably `int`, just like what it is on Linux. [09:51:00] yes but that's still a compiler-specific reference; I still don't know hwere Microsoft keeps its ABI documentation, and I'm still wondering what you mean by "the ABI != on Windows" with regards to establishing that guarantee [09:52:13] This is already the ABI documentation: https://docs.microsoft.com/en-us/cpp/cpp/char-wchar-t-char16-t-char32-t [09:52:15] Title: char, wchar_t, char16_t, char32_t | Microsoft Docs (at docs.microsoft.com) [09:52:19] It describes C++ types, [09:53:09] oh, ok [09:54:47] I assume by the != statement you mean code that doesn't make any windows API calls can theoretically be compiled any which way, right [09:55:05] yes. think about MSYS and Cygwin. [09:55:21] They have 8-byte `long` and 4-byte `wchar_t`. [09:57:37] right, except the code I'm trying to compile does use the Windows API, so that wouldn't apply to me [09:57:43] I assume [09:57:53] it wouldn't. [09:59:12] On Windows it is sometimes necessary to assume specific ABI definition. For example, when a callback function returning a `DWORD` is to be declared in a header, in order to prevent `#include`'ing windows.h, you can just write `unsigned long` there. [09:59:32] This is guaranteed to work on Windows. Linux will say otherwise. [10:00:41] We all know `#include ` in a public header lets the genie out of the bottle, doesn't it? [10:04:24] the zombie of win32_lean_and_mean lives forever [10:04:53] of course now we have stdint.h and cstdint (which took longer because lolC++03) which helps stuff [10:06:19] no `uint32_t` is `unsigned int` while `DWORD` is `unsigned long` hence they are incompatible. :( [10:06:39] in what sense [10:06:55] a `unsigned int *` cannot be converted to `unsigned long *` implicitly. [10:07:41] the C standard says they are distinct pointer types and are not compatible, although `unsigned int` and `unsigned long` might have the same bit representation and alignment requirement. [10:08:04] oh [10:08:22] casting would indeed make code compile, but I tend to keep away from them unless necessary. [10:08:24] wel yeah, but we haven't left the world of windows-specific code yet [10:08:38] my point was more we don't need to use names like DWORD anymore [10:08:51] of course it's easier to do so [10:09:04] just use `uint32_t`. [10:09:44] I just tested GCC 8 today and noticed they had added a warning for casting between incompatible function pointer types. [10:10:10] So casting from `unsigned (*)(void)` to `unsigned long (*)(void)` now results in a warning. [10:10:43] With `-Werror` it is a hard error. This can be worked around by casting the operand to an intermediate result of `intptr_t`. [10:10:59] ... not so serious. [10:11:42] oh good I wonder what else will break :D [10:12:19] though the docs for dlsym() tell you what you should do instead for systems that use libdl (cast the address of your destination variable to void**) [10:13:23] POSIX requires casting from `void *` to function pointers to work explicitly (see the docs for `dlsym()`). I am not sure what GCC people think about it. [10:13:45] yes that's what I just said =P it avoids the problem entirely [10:13:49] C++ says this is 'conditionally supported' and it is not a warning or error there. [10:13:50] dlsym already returns void* [10:14:13] something like dlsym would require an ABI guarantee on the matter anyway [10:14:16] by definition [10:14:32] Casting is evil. Double casting is double evil. So I keep myself away from them. [10:15:03] sadly this is C (and C++) =P [10:15:25] for `*-w64-mingw32` targets it is safe to cast between `unsigned short`, `wchar_t` and `char16_t`. [10:15:33] as well as pointers to them. [10:16:30] you just need to `static_assert` it, so something naughty will not compile. [12:36:14] actually I didn't notice that last message until just now [12:36:23] I was asking because I was sitting here thinking such a static_assert was unnecessary } clang debate: http://clang-developers.42468.n3.nabble.com/Is-that-getting-wchar-t-to-be-32bit-on-win32-a-good-idea-for-compatible-with-Unix-world-by-implement-td4045412.html so I'm not sure what is correct, but I do need to find out */ #include #if WCHAR_MAX > 0xFFFF #error unexpected: wchar_t larger than 16-bit on a Windows ABI build; contact andlabs with your build setup information #endif #endif