Khaine
#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.
  • Najlepsze
  • Wszystkie komentarze
Vetinari
@Khaine: Jak masz struct to patrzysz jakie w 32 bit były typy i używasz odpowiedników z ctype: uint32_t itp
KrzaQ2
@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.
Khaine
Khaine Autor
0
@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ć :/
Khaine
Khaine Autor
0
@KrzaQ2: Co byś ogółem zalecał zrobić w tej sytuacji? Jak odzyskać te pola?
Khaine
Khaine Autor
0
@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?
Vetinari
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ą
Khaine
Khaine Autor
0
@Vetinari:

https://gist.github.com/anonymous/d6b7654bdfce13e97e7e

To jest cały struct. On jest prosty, ale zawiera funkcje. A ja chcę wybebeszyć pola tylko i wyłącznie.

Ah, problem jest w tym, że ja nie mam możliwości go skompilować na tym starym dziadostwie za bardzo. Muszę szukać po omacku jak już. Mając po prostu zapisane pliki z już skompilowanego programu.
Vetinari
@Khaine: Jestem na 99% pewien że tylko pola zapisza się do pliku, otwórz taki plik w hex edytorze i sprawdź czy nie ma tam 12 bajtów tylko?
Khaine
Khaine Autor
0
@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)
crystalDesign
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
Khaine
Khaine Autor
0
@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.
Vetinari
@Khaine: To zrób struct który ma w środku 3x uint32_t (oznaczony jako packed) i wczytaj freadem początek pliku i sprawdź czy jest ok
Khaine
Khaine Autor
0
@Vetinari: Ale na czym? W Qt?
Vetinari
@Khaine: W czystym C++ na początek
Vetinari
@Khaine: Albo możesz w Qt, bo widzę że tak będzie łatwiej (kod z pamięci bez sprawdzania):

#include
#include

QDataStream* stream
Khaine
Khaine Autor
0
@Vetinari:

Tak wstępnie. Wychodzi na to, że same pola są chyba.
Kaczus2B
Kaczus2B
@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.
Khaine
Khaine Autor
  • adult
0
Treść przeznaczona dla osób powyżej 18 roku życia...