Определить порядок следования байтов с помощью CMake

Моя библиотека должна считывать целые числа с прямым порядком байтов (4 байта) и преобразовывать их в порядок байтов хоста для обработки. В то время как на * nix ntohl работало под Windows, использование ntohl требует использования Ws2_32.dll (Winsock).

Такую зависимость я бы предпочел устранить. Самый простой способ сделать это, по-видимому, состоит в том, чтобы написать мою собственную функцию замены байтов (тривиальное упражнение, учитывая, что производительность не является реальной проблемой). Однако для этого требуется способ определить порядок следования байтов системы, в которой компилируется моя библиотека (так что я могу #ifdef отключить функцию подкачки в системах с прямым порядком байтов).

Поскольку стандартного определения порядка следования байтов в препроцессоре не существует, кажется, что его необходимо определить с помощью моей системы сборки (cmake). Каков наилучший способ сделать это? (Я устал от решений типа «скомпилировать тестовый файл и посмотреть», поскольку они могут препятствовать кросс-компиляции.)


person Freddie Witherden    schedule 06.10.2010    source источник
comment
Примечание: CMake действительно имеет разумную поддержку кросс-компиляции. Для проверок, требующих запуска тестовой программы, он создает тестовую программу, а затем ожидает, пока вы установите переменные кэша на правильный результат. См. paraview.org/Wiki/CMake_Cross_Compiling . Проголосуйте за заботу о кросс-компиляции.   -  person Jack Kelly    schedule 08.10.2010


Ответы (2)


Отредактировано: я вижу, что cmake имеет сценарий TestBigEndian.cmake, но он выполняет компиляцию и тестовый запуск, чтобы увидеть, является ли система Big Endian или нет, а это не то, что вы хотите делать.

Вы можете проверить порядок следования байтов системы в своей собственной программе с помощью такой функции.

bool isLittleEndian()
{
    short int number = 0x1;
    char *numPtr = (char*)&number;
    return (numPtr[0] == 1);
}

В основном создайте целое число и прочитайте его первый байт (наименее значащий байт). Если этот байт равен 1, то система с прямым порядком байтов, в противном случае — с обратным порядком байтов.

Однако это не позволяет вам определять порядок следования байтов до времени выполнения.

Если вы хотите, чтобы время компиляции определяло порядок байтов системы, я не вижу другой альтернативы, кроме «создания тестовой программы, а затем компиляции моей реальной программы» а-ля cmake или выполнения исчерпывающих проверок для определенных макросов, определенных компиляторами, например __BIG_ENDIAN__ в GCC 4.x.

ОБНОВЛЕНО Возможно, вы также захотите взглянуть на собственный endian.hpp Boost в качестве примера. http://www.boost.org/doc/libs/1_43_0/boost/detail/endian.hpp

person wkl    schedule 06.10.2010
comment
Однако это не позволяет вам определять порядок следования байтов до времени выполнения. - Вы можете сделать что-то подобное, и это должно оцениваться во время компиляции: const bool g_isLittleEndian=isLittleEndian(); - person darklon; 31.12.2015
comment
Переменная @darklon const не оценивается строго во время компиляции. Он может и будет оцениваться во время выполнения, поскольку isLittleEndian() использует переменные. Чтобы сделать его строго оцениваемым во время компиляции, следует использовать ключевое слово constexpr или технику метапрограммирования шаблонов. (Причина, по которой я думал, что const bool g_isLittleEndian=isLittleEndian(); будет оцениваться во время выполнения, заключается в том, что (char*)(& number) не является постоянным выражением. Это то, что говорит GCC, когда вы объявляете numPtr как constexpr) - person minary; 20.05.2017
comment
для получения дополнительной информации о том, что может быть объявлено constexpr, см. эту ссылку - person CrepeGoat; 27.05.2018

Также это может сделать эта функция CMake, http://www.cmake.org/cmake/help/v3.5/module/TestBigEndian.html

include (TestBigEndian)
TEST_BIG_ENDIAN(IS_BIG_ENDIAN)
if(IS_BIG_ENDIAN)
 message(STATUS "BIG_ENDIAN")
else()
 message(STATUS "LITTLE_ENDIAN")
endif()

Я думаю, что поддерживается только с CMake 3.0

person TheHube    schedule 19.03.2015