3

I have a 32bit and a 64bit version of my application and need to do something special in case it's the 32bit version running on 64bit Windows. I'd like to avoid platform specific calls and instead use Qt or boost. For Qt I found Q_PROCESSOR_X86_32 besides Q_OS_WIN64 and it seems this is exactly what I need. But it doesn't work:

#include <QtGlobal>

#ifdef Q_PROCESSOR_X86_64
  std::cout << "64 Bit App" << std::endl;
#endif

#ifdef Q_PROCESSOR_X86_32
  std::cout << "32 Bit App" << std::endl;
#endif

This puts out nothing when running the 32 bit App on my 64 bit Windows 7. Do I misunderstand the documentation of these global declarations?

Since there's some confusion: This is not about detecting the OS the app is currently running on, it's about detecting the "bitness" of the app itself.

DenverCoder21
  • 879
  • 3
  • 16
  • 34
  • Would `_WIN64` do? – Biffen Apr 15 '16 at 14:07
  • I need a combination. Of Q_OS_WIN/64 and Q_PROCESSOR_X86_32/64. Like: if(Win64 && AppIs32) do A; if(Win64 && AppIs64) do B; if(Win32 && AppIs32) do C; if(Win32 && AppIs64) do D; Q_OS_WIN64 works as expected from the docs btw. – DenverCoder21 Apr 15 '16 at 14:10
  • I really don't understand the problem. Sorry. – Biffen Apr 15 '16 at 14:13
  • I need to know if Windows is 32 or 64 bit. Plus I need to know about my application itself whether it's 32 or 64 bit. – DenverCoder21 Apr 15 '16 at 14:15
  • 2
    You cannot make that decision at compile-time. For your 32-bit build you will have to query the OS, at runtime, using e.g. [IsWow64Process](https://msdn.microsoft.com/en-us/library/windows/desktop/ms684139.aspx). – IInspectable Apr 15 '16 at 14:16
  • Ok. So do you know what Q_PROCESSOR_X86_32 is used for then? – DenverCoder21 Apr 15 '16 at 14:19
  • `Q_PROCESSOR_X86_32` is defined, when you compile a 32-bit version of your application. A 32-bit version of your application can run on a 32-bit OS or a 64-bit OS. A 64-bit version of your application can only run on a 64-bit OS. – IInspectable Apr 15 '16 at 14:20
  • Possible duplicate of [Is there a Windows API call that will tell me if I'm running on a 64-bit OS?](http://stackoverflow.com/questions/1646418/is-there-a-windows-api-call-that-will-tell-me-if-im-running-on-a-64-bit-os) – IInspectable Apr 15 '16 at 14:24
  • 2
    @IInspectable: Not a duplicate, Windows API versus Qt. – MSalters Apr 15 '16 at 14:35
  • @MSalters: You are right, the questions asked are different. However, the answer is the same, since there is no cross-platform way to do this using Qt (or Boost). The proposed [Qt-based answer](http://stackoverflow.com/a/36650033/1889329) is cross-platform. But ever-so-subtly wrong. – IInspectable Apr 15 '16 at 14:47
  • 3
    This question stopped making any sense. First you say, that you need to do something special, if a 32-bit build of your application runs on a 64-bit OS. And in your attempt to clarify the confusion, you contradict yourself by saying, that you do not need to detect the bitness of the OS. It's time to make up your mind. – IInspectable Apr 15 '16 at 15:29

5 Answers5

4

Take a look at QSysInfo::currentCpuArchitecture(): it will return a string containing "64" in it when running on a 64-bit host. Similarly, QSysInfo::buildCpuArchitecture() will return such string when compiled on a 64-bit host:

bool isHost64Bit() {
  static bool h = QSysInfo::currentCpuArchitecture().contains(QLatin1String("64"));
  return h;
}
bool isBuild64Bit() {
  static bool b = QSysInfo::buildCpuArchitecture().contains(QLatin1String("64"));
  return b;
}

Then, the condition you want to detect is:

bool is32BuildOn64Host() { return !isBuild64Bit() && isHost64Bit(); }

This should be portable to all architectures that support running 32-bit code on a 64-bit host.

Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
Murphy
  • 3,827
  • 4
  • 21
  • 35
  • This does the trick. Thank you! @AdrianoReptti: I'm not trying to detect the OS version but the version of the app itself. – DenverCoder21 Apr 15 '16 at 14:56
  • 1
    @DenverCoder21: You already **know** the bitness of your application: You set it in your build environment. – IInspectable Apr 15 '16 at 14:58
  • Then please show me some code that calls function A if the App is 32bit and runs on Win64, function B if the app is 32bit and runs on Win32 and function C if 64bit and runs on Win64. – DenverCoder21 Apr 15 '16 at 15:03
  • 1
    @DenverCoder21 then you *are* trying to detect the OS version. You're contradicting yourself! And have you tested this solution with a 32-bit build on a 64-bit OS? – Mark Ransom Apr 15 '16 at 15:06
  • As I said, I need a combination of both. Of course I also need to know the OS version, but I also need to differentiate between the app version to implement a different behaviour. – DenverCoder21 Apr 15 '16 at 15:09
  • A and B can be done at compile-time (because 64 bit won't run on 32 bit OS) and you already have them but for C you have to detect OS (at run-time!). I repeat: OS, not CPU. – Adriano Repetti Apr 15 '16 at 15:59
3

You can use Q_PROCESSOR_WORDSIZE (or here). I'm surprised it's not documented because it's not in a private header (QtGlobal) and is quite handy.

It could be more preferable for some use cases because it doesn't depend on processor architecture. (e.g. it's defined the same way for x86_64 as well as arm64 and many others)

Example:

#include <QtGlobal>
#include <QDebug>

int main() {
#if Q_PROCESSOR_WORDSIZE == 4
    qDebug() << "32-bit executable";
#elif Q_PROCESSOR_WORDSIZE == 8
    qDebug() << "64-bit executable";
#else
    qDebug() << "Processor with unexpected word size";
#endif
}

or even better:

int main() {
    qDebug() << QStringLiteral("%1-bit executable").arg(Q_PROCESSOR_WORDSIZE * 8);
}
Burak Arslan
  • 7,671
  • 2
  • 15
  • 24
1

Preprocessor directives are evaluated at compile-time. What you want to do is to compile for 32 bit and at run-time check if you're running on a 64 bit system (note that your process will be 32 bit):

#ifdef Q_PROCESSOR_X86_32
  std::cout << "32 Bit App" << std::endl;

  BOOL bIsWow64 = FALSE;
  if (IsWow64Process(GetCurrentProcess(), &bIsWow64) && bIsWow64)
      std::cout << "Running on 64 Bit OS" << std::endl;
#endif

That example is Windows specific. There is not a portable way to do it, on Linux you may use run system("getconf LONG_BIT") or system("uname -m") and check its output.

Adriano Repetti
  • 65,416
  • 20
  • 137
  • 208
  • Uhm... no. That portable code may be portable. But it's wrong. It will **never** output *"Running on 64 Bit OS"*, even if it does. Like the preprocessor macro, the sizeof operator is evaluated at compile time. – IInspectable Apr 15 '16 at 14:21
  • I think I got what you guys mean. Thank you – DenverCoder21 Apr 15 '16 at 14:32
1

You can use GetNativeSystemInfo (see below) to determine the OS's version. As other already mentioned, the App's version is determined at the compile-time.

_SYSTEM_INFO sysinfo;
GetNativeSystemInfo(&sysinfo);
if (sysinfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
{
     //this is a 32-bit OS
}
if (sysinfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
{
     //this is a 64-bit OS
}
0

The correct name is Q_PROCESSOR_X86_32 or Q_PROCESSOR_X86_64.

However if it happens your application runs on ARM in future this will not work. Rather consider checking sizeof(void *) or QT_POINTER_SIZE for example.

Additionally note that on Windows the GUI applications usually can't output to stdout so it may work but doesn't show anything. Use eithrr debugger or message box or output to some dummy file instead.

Zbynek Vyskovsky - kvr000
  • 18,186
  • 3
  • 35
  • 43