Wpis z mikrobloga

#programowanie #cpp #qt

Mam problem programirki. Robię z kolegą remake pewnego starego programu korzystając z bibliotek Qt. No i natrafiliśmy na kłopot. Po pierwsze wersja oryginalna tego programu jest skompilowana w 32 bitach na jakimś archaicznym środowisku CodeGear. Nawet nie wiem w sumie jaki tam jest kompilator. My korzystamy z 64 bitowego MSVC AMD.

Problem jest następujący. Stary program ma sobie wczytywanie i zapisywanie plików jakiegoś swojego formatu. To jest oczywiście byte array. Wymagana jest wsteczna kompatybilność z odczytywaniem tych plików, więc trzeba te stare pliki jakoś wczytywać i zapisywać do tego samego formatu. I nic nie jest problemem poza jednym miejscem - gdzie funkcja C++ fwrite/fread zapisuje/odczytuje structa w całości zajmując miejsce w pamięci na sizeof(struct). No i Qt nie ogarnia z tego co mi wiadomo czegoś takiego. Operatory >> QDataStream obsługują tylko typy podstawowe + qtowe, drugą opcją jest ReadRawData, więc po prostu wzięcie tego nieszczęsnego sizeof i odczytanie tablicy bajtów na yolo. No ale jak ja mam z tego skleić znowu structa? Ja mam kod źródłowy tego structa i już go wrzuciłem do nowego programu, ale nie jestem pewien czy rzutowanie tego tutaj zadziała? A nawet jeśli da się rzutować char array na struct, to czy kompilator na jakim to było zrobione nie ma znaczenia? W sensie - czy on odzyska wtedy faktycznie oryginał?

Ogółem chciałbym wiedzieć jak to zrobić po Qtowemu i czy to jest w ogóle możliwe. Bo opcją ostateczną jest po prostu, cóż - użycie tych samych funkcji C++, którymi plik był zapisywany. Ale chciałbym tego uniknąć aby po prostu nie sklejać frankenstaina raz odczytując tak a raz tak.

Prawda jest taka, że z tego structa interesują mnie dosłownie trzy pola będące unsigned intami, ale nie jestem wróżką aby wiedzieć, które bajty w zajmowanej pamięci to właśnie te wartości. A tam jeszcze wchodzą takie śmieci jak jakieś funkcje + konstruktory. Gdybym wiedział, które to bajty, to bym je po prostu wybebeszył z char array, rzutował na uint i miał to w dupie.
  • 20
@Khaine: long, wskaźniki i inne typy mogą mieć róƶne wielkości pomiędzy architekturami.

Na windowsie na pewno x64 i x86 mają róƶne wielkości wskaźników (chociaƶ przy fread raczej ich tam nie ma), ale mimo wszystko bym uwaƶał z wczytywaniem kodu w całości i wypełniał/zapisywał te struktury po kaƶdym członku.
@KrzaQ2: No dlatego się obawiam, że nawet używając fwrite i fread z C++ samego w sobie ja nie odzyskam tego structa po prostu. Ja nic nie poradzę, autor starego programu wpadł na genialny pomysł zapisania structa w całości zamiast wybebeszyć składowe i zserializować :/
@Vetinari: No dobra, odczytuję tablicę charów. Skąd mam wiedzieć, które to konkretnie bajty? Ja mam pliki zapisu z tego programu, więc mogę obejrzeć plik zserializowany od środka (tylko nie mam bladego pojęcia jak ja znajdę początek tego structa). Ale jak go rozłożyć na czynniki pierwsze, żeby wiedzieć, które konkretnie bajty licząc od początku zapisu structa przechowują te uinty? Jest może jakiś program który mi pomoże w takim odszyfrowywaniu?
fread przyjmuje też całą strukturę na raz. Zrób z tego ładna klasę i tyle, możesz oczywiście wczytać to bajt po bajcie i potem poskładać do kupy ale to bez sensu. Możesz pokazać tego structa? Ewentualnie wpisz do structa do pól ktorych potrzebujesz AAAA, BBBB hex itd, zapisz do pliku i otwórz w hex edytorze, będziesz wiedział które bajty Cię interesują
@Vetinari: No tu jest kolejny problem. Ten plik binarny jest duży ( ͡º ͜ʖ͡º) To jest tylko jedna zmienna - czas. Poza tym tam jest kupa innego gówna jeszcze. Ale da radę po dacie chyba wyszukać prawidłowość, bo to się powtarza "co wiersz" (zapis wierszami - data, godzina, x wartości danych, powtórz)
ale w strukturze przechowywanej w pamięci, są tylko czyste dane, nie ma tam nic związanego z funkcjami - bo po co?
jak w klasie są zawarte funkcje wirtualne, to wtedy ewentualnie jest jeszcze vtable
@crystalDesign: No jeśli funkcja fwrite tak działa to ok. Ale tam jest wpisany cały sizeof(struct). Nie mogę tego skompilować na tym starym dziadzie, żeby zobaczyć ile dokładnie ten sizeof na tamtym kompilatorze ma. Bo wtedy bym wiedział, czy tam jest coś więcej niż pola.
@Khaine: Albo możesz w Qt, bo widzę że tak będzie łatwiej (kod z pamięci bez sprawdzania):

#include
#include

QDataStream* stream = ...;

uint32t days = 0;
uint32
t secs = 0;
uint32_t usecs = 0;

stream->readRawData(&days, 4);
stream->readRawData(&secs, 4);
stream->readRawData(&usecs, 4);

qDebug() << days << " " << secs << " " << usecs;
@Khaine: Sprawdz jakim kompilatorem byl kompilowany ten "stary dziad", bo jak tak niczym sie nie przejmował, to upakowaniem struktur też nie wiadomo, czy sie przejmował... Niestety musisz przeprowadzic analize i testy.
@Kaczus2B: Odpaliłem to gówno na maszynie wirtualnej (bo to jeszcze XP) i też sizeof pokazuje 12 bajtów. No wychodzi na to, że trzyma tylko te pola. Mam nadzieję, że w takiej samej kolejności.