Портирование кода сериализации данных из C ++ linux / mac в C ++ windows - PullRequest
1 голос
/ 16 ноября 2011

У меня есть программная среда, скомпилированная и успешно работающая как на Mac, так и на Linux. Я сейчас пытаюсь перенести его на Windows (используя Mingw). Пока что у меня есть программное обеспечение, которое компилируется и работает под Windows, но оно неизбежно глючит. В частности, у меня проблема с чтением данных, которые были сериализованы в macos (или linux) в версию программы для Windows (segfaults).

Процесс сериализации сериализует значения простых переменных (long, ints, doubles и т. Д.) На диск.

Это код, который я использую:

#include <iostream>
#include <fstream>

template <class T>
void serializeVariable(T var, std::ofstream &outFile)
{
    outFile.write (reinterpret_cast < char *>(&var),sizeof (var));
}

template <class T>
void readSerializedVariable(T &var, std::ifstream &inFile)
{
inFile.read (reinterpret_cast < char *>(&var),sizeof (var));
}

Таким образом, чтобы сохранить состояние группы переменных, я вызываю serializeVariable для каждой переменной по очереди. Затем, чтобы прочитать данные обратно, вызываются readSerializedVariable в том же порядке, в котором они были сохранены. Например, чтобы сохранить:

::serializeVariable<float>(spreadx,outFile);
::serializeVariable<int>(objectDensity,outFile);
::serializeVariable<int>(popSize,outFile);

И читать:

::readSerializedVariable<float>(spreadx,inFile);
::readSerializedVariable<int>(objectDensity,inFile);
::readSerializedVariable<int>(popSize,inFile);

Но в Windows это чтение сериализованных данных не выполняется. Я предполагаю, что Windows сериализует данные немного по-другому. Интересно, есть ли способ, которым я мог бы изменить вышеуказанный код, чтобы данные, сохраненные на любой платформе, можно было читать на любой другой платформе ... какие-нибудь идеи?

Приветствия

Бен.

Ответы [ 4 ]

2 голосов
/ 16 ноября 2011

Двоичная сериализация, подобная этой, должна нормально работать на этих платформах.Вы должны соблюдать чередование, но это тривиально.Я не думаю, что у этих трех платформ есть какие-либо конфликты в этом отношении.

Хотя вы действительно не можете использовать такие спецификации типов как свободные.Размеры int, float, size_t могут изменяться на разных платформах.

Для целочисленных типов используйте типы строгого размера, указанные в заголовке cstdint.uint32_t, int32_t и т. Д. Windows не имеет доступного заголовка iirc, но вместо этого вы можете использовать boost / cstdint.hpp.

Плавающая точка должна работать как большинство компиляторовследуйте тем же спецификациям IEEE.

C - Сериализация чисел с плавающей запятой (числа с плавающей запятой, двойные числа)

Двоичная сериализация действительно требует тщательного модульного тестирования.Я настоятельно рекомендую потратить время.

2 голосов
/ 16 ноября 2011

это просто дикая догадка, я не могу тебе больше помочь.Моя идея состоит в том, что порядок байтов различен: порядковый номер с прямым порядком байтов против порядкового номера.Таким образом, все, что больше одного байта, будет испорчено при загрузке на машине с обратным порядком.

Например, я нашел этот код в msdn:

int isLittleEndian() {
    long int testInt = 0x12345678;
    char *pMem;

    pMem = (char *) testInt;
    if (pMem[0] == 0x78)
        return(1);
    else
        return(0);
}

Я думаю, выбудет иметь разные результаты на Linux против Windows.Наилучший случай был бы, если бы у вашего компилятора была опция флага, чтобы использовать один или другой формат.Просто установите его одинаковым на всех машинах.

Надеюсь, это поможет, Алекс

1 голос
/ 16 ноября 2011

Еще одна дикая догадка: вы забыли открыть файл в двоичном режиме чтения и в файловых потоках Windows преобразовать последовательность с 13,10 в 10.

0 голосов
/ 16 ноября 2011

Рассматривали ли вы использование библиотек или форматов сериализации, например:

  • XDR (поддерживается libc) или ASN1
  • s11n (библиотека сериализации C ++)
  • Json , очень простой текстовый формат со многими библиотеками для него, например JsonCpp , Jansson , Jaula, ....)
  • YAML , более мощный текстовый формат со многими библиотеками
  • или даже XML , который часто используется дляцели сериализации ...

(А для сериализации скаляров должны помочь htonl и сопутствующие процедуры)

...