15

Is there a way to forward-declare the HINSTANCE type from the WinAPI without including the full (and big) windows.h header?

For example, if I have a class RenderWindow which owns an HINSTANCE mInstance, i will have to include windows.h in RenderWindow.h. So everything that needs RenderWindow also has to include windows.h.

I tried including windef.h but this seems to need some things from windows.h. :-( If I can't forward declare it, is there at least a portable way to use something like long mInstance in RenderWindow instead of HINSTANCE?

abenthy
  • 883
  • 1
  • 8
  • 23
  • Is including windows.h actually causing you any problems? –  Apr 04 '10 at 13:47
  • 1
    not directly, but i don't like including it because one has to sometimes undefine `min` and `max` macros and i think it increases compile time / look up etc. – abenthy Apr 04 '10 at 13:52
  • 3
    `#define NOMINMAX` before including ``. – James McNellis Apr 04 '10 at 15:11
  • 4
    I can think of a half dozen good reasons to want to avoid including it. min/max, macros of commonly used names (CreateWindow, for example), and the fact that it doesn't compile as C++. You have to enable Microsoft's language extensions. windows.h is badly behaved in every possible way. – jalf Apr 04 '10 at 16:46
  • For those landed here looking for replacement of HINSTANCE with C pointer type void * (I give up for now) there is a [heated discussion about its opacity](http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/54b9f116-412f-4bf8-9012-260c56037d0a). – Salvador Apr 04 '14 at 16:56
  • @abenthy you should not have min\max macros anyway. there should be safer and perhaps even faster `std::min` \ `std::max` – Swift - Friday Pie Nov 26 '21 at 17:51

5 Answers5

9

HINSTANCE is declared in WinDef.h as typedef HINSTANCE__* HINSTANCE;

You may write in your headers:

#ifndef _WINDEF_
class HINSTANCE__; // Forward or never
typedef HINSTANCE__* HINSTANCE;
#endif

You will get compilation errors referencing a HINSTANCE when WinDef.h is not included.

Alain Rist
  • 827
  • 6
  • 11
  • 3
    That's the hack i was searching for, very clever! (`HINSTANCE__` seems to be `struct` here on MSVC2005) – abenthy Apr 04 '10 at 20:16
  • 3
    It's no hack, Windef.h is written to allow it :-) Declaring a class instead of a struct guarantees a compiler error if Windef.h is included later, which means bad file structure design. – Alain Rist Apr 04 '10 at 20:42
  • 1
    I see, but if i i use class i get a compiler error if i later include `windows.h` in my implementation file, in which i need `windows.h`. Is it bad file structure to use you're suggested typedef in a header file and include `windows.h` in the corresponding source file? – abenthy Apr 05 '10 at 06:36
  • 2
    If you need Windows.h in *this* compilation unit, include it at first, as other library headers, before your own. – Alain Rist Apr 05 '10 at 07:19
  • Sorry to tumbleweed this, but I am having problems using it (and need it!) - I am trying to compile some C code on *nix. Using this excellent solution leads to `error: unknown type name 'class'`. My C is poor :\ @AlainRist – jtlz2 Jan 23 '18 at 12:54
  • @jtlz2 ask a separate question – YSC Nov 23 '21 at 08:50
  • That'd invoke undefined behavior. `HINSTANCE__` is a [reserved identifier](https://en.cppreference.com/w/cpp/language/identifiers#In_declarations). If that snippet of code is included anywhere: the result of compilation is, by definition, [NOT A PROGRAM](https://en.cppreference.com/w/cpp/language/ub). I know nobody cares. Call me nobody. (I also read terms and conditions) – viraltaco_ Nov 23 '21 at 11:25
5

You could declare it void* and cast the errors away. This is close to a never-ending battle though, sooner or later you'll get tripped up. Use pre-compiled headers so you don't care about the size of windows.h

stdafx.h:

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
3

For example, if I have a class RenderWindow which owns an HINSTANCE mInstance, i will have to include windows.h in RenderWindow.h. So everything that needs RenderWindow also has to include windows.h.

Have you looked at the Pimpl idiom? This allows you to hide private members. A side-effect is that you don't have to include their headers in your class' header.

sbi
  • 219,715
  • 46
  • 258
  • 445
1

Hey @NoSenseEtAl I guess we are still there.

In 2021, HINSTANCE is defined in <minwindef.h>. Including directly <minwindef.h> gives the error: "No Target Architecture"

To work around the error, do the following (assuming building for x64):

#define _AMD64_
#include <minwindef.h>

int main() {
    HINSTANCE h;
}

Note that the macro _AMD64_ is not documented, it starts with underscore, so not to be defined by user.

And it is defined only by <Windows.h>, so there's no smaller header to include make it defined.

Apparently there's more hope that Windows SDK will work fine with Modules, so can fix the build speed by Modules instead.

Alex Guteniev
  • 12,039
  • 2
  • 34
  • 79
1

The best portable way to deal with handles without header including is reinterpret_casting them to a type with exactly the same size.

Most handles have pointer size1. So void* or uintptr_t will do. Examples:

  • _beginthreadex returns uintptr_t instead of HANDLE to a thread.
  • MSVC thread::native_handle returns void*

Be sure to static_assert for type sizes in a place where you see the type.

1 Few handles don't have pointer size, I can only recall the one returned by AcquireCredentialsHandle.

Alex Guteniev
  • 12,039
  • 2
  • 34
  • 79