Forward declare HINSTANCE and friends
Asked Answered
E

5

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?

Extinct answered 4/4, 2010 at 13:43 Comment(6)
Is including windows.h actually causing you any problems?Bevy
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.Extinct
#define NOMINMAX before including <windows.h>.Excuse
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.Holman
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.Apodaca
@Extinct you should not have min\max macros anyway. there should be safer and perhaps even faster std::min \ std::maxSenhauser
Z
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.

Zarathustra answered 4/4, 2010 at 16:57 Comment(7)
That's the hack i was searching for, very clever! (HINSTANCE__ seems to be struct here on MSVC2005)Extinct
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.Zarathustra
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?Extinct
If you need Windows.h in this compilation unit, include it at first, as other library headers, before your own.Zarathustra
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 :\ @AlainRistVendetta
@Vendetta ask a separate questionRetarded
That'd invoke undefined behavior. HINSTANCE__ is a reserved identifier. If that snippet of code is included anywhere: the result of compilation is, by definition, NOT A PROGRAM. I know nobody cares. Call me nobody. (I also read terms and conditions)Monogram
O
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>
Osteopath answered 4/4, 2010 at 13:51 Comment(0)
O
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.

Ornithosis answered 4/4, 2010 at 13:53 Comment(2)
Yup, Pimpl is how I usually do this.Holman
Thanks for the suggestion. I never the less have to say that i prefer Alain Rist's solution.Extinct
K
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.

Kimes answered 23/11, 2021 at 15:25 Comment(0)
K
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.

Kimes answered 23/11, 2021 at 15:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.