У меня есть 32-битная и 64-битная версия моего приложения, и мне нужно сделать что-то особенное на случай, если это 32-битная версия, работающая на 64-битной Windows. Я хотел бы избегать вызовов, специфичных для платформы, и вместо этого использовать Qt или boost. Для Qt я нашел Q_PROCESSOR_X86_32 Кроме того Q_OS_WIN64 и кажется, это именно то, что мне нужно. Но это не работает:
#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
Это ничего не дает при запуске 32-битного приложения на моей 64-битной Windows 7. Не понимаю ли я документацию этих глобальных деклараций?
Поскольку существует некоторая путаница: речь идет не об обнаружении ОС, в которой в данный момент выполняется приложение, а об обнаружении «битности» самого приложения.
Взгляни на QSysInfo::currentCpuArchitecture()
: он вернет строку, содержащую "64"
в нем при работе на 64-битном хосте. Так же, QSysInfo::buildCpuArchitecture()
вернет такую строку при компиляции на 64-битном хосте:
bool isHost64Bit() {
static bool h = QSysInfo::currentCpuArchitecture().contains(QLatin1String("64"));
return h;
}
bool isBuild64Bit() {
static bool b = QSysInfo::buildCpuArchitecture().contains(QLatin1String("64"));
return b;
}
Тогда условие, которое вы хотите обнаружить:
bool is32BuildOn64Host() { return !isBuild64Bit() && isHost64Bit(); }
Это должно быть переносимо на все архитектуры, которые поддерживают запуск 32-битного кода на 64-битном хосте.
Правильное имя Q_PROCESSOR_X86_32
или же Q_PROCESSOR_X86_64
,
Однако, если это произойдет, ваше приложение будет работать на ARM в будущем, это не будет работать. Скорее рассмотрите проверку sizeof(void *)
или же QT_POINTER_SIZE
например.
Дополнительно обратите внимание, что в Windows приложения с графическим интерфейсом обычно не могут выводить на стандартный вывод, поэтому он может работать, но ничего не показывает. Вместо этого используйте отладчик eithrr или окно сообщения или вывод в какой-нибудь фиктивный файл.
Директивы препроцессора оцениваются в время компиляции. Что вы хотите сделать, так это скомпилировать 32-битную версию и проверить во время выполнения, работаете ли вы в 64-битной системе (обратите внимание, что ваш процесс будет 32-битным):
#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
Этот пример Специфичный для Windows. Существует не портативный способ сделать это, на Linux вы может использовать бег system("getconf LONG_BIT")
или же system("uname -m")
и проверьте его вывод.
Вы можете использовать GetNativeSystemInfo (см. Ниже), чтобы определить версию ОС. Как уже упоминалось, версия приложения определяется во время компиляции.
_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
}
Ты можешь использовать Q_PROCESSOR_WORDSIZE (или же Вот). Я удивлен, что это не задокументировано, потому что оно не находится в частном заголовке (QtGlobal) и довольно удобно.
Это может быть более предпочтительным для некоторых случаев использования, потому что это не зависит от архитектуры процессора. (например, он определен одинаково для x86_64, а также для arm64 и многих других)
Пример:
#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
}
или даже лучше:
int main() {
qDebug() << QStringLiteral("%1-bit executable").arg(Q_PROCESSOR_WORDSIZE * 8);
}