If you're writing C++, why not use C++ I/O, rather than using the older C stdio based I/O? Still, you should be able to write binary data on Windows and read it on Linux, with only a little effort.
Windows program to write some binary data:
#include <iostream>
#include <fstream>
struct CTE {
unsigned short Version;
unsigned short Signature;
unsigned short core;
unsigned short edition;
};
struct GTE {
unsigned char LTL : 1;
unsigned char trans : 1;
uint_least8_t wcountry;
uint_least8_t wlanguage;
unsigned int count;
int WIDTH;
int HEIGHT;
};
int main()
{
std::cout << "size of cte = " << sizeof(CTE) << '\n';
std::cout << "sizeof gte = " << sizeof(GTE) << '\n';
std::fstream data("C:\\tmp\\chopin.dat", std::ios::out | std::ios::binary);
CTE cte{ 1, 15, 32, 1 };
GTE gte{ 0, 1, 111, 222, 0, 456, 123 };
data.write(reinterpret_cast<char*>(&cte), sizeof cte);
for (size_t i = 1; i < 11; ++i) {
gte.count = i;
data.write(reinterpret_cast<char*>(>e), sizeof gte);
}
std::cout << "gte: "
<< +gte.LTL << ' '
<< +gte.trans << ' '
<< +gte.wcountry << ' '
<< +gte.wlanguage << ' '
<< gte.count << ' '
<< gte.WIDTH << ' '
<< gte.HEIGHT << '\n';
return 0;
}
Compiling and running this produces:
size of cte = 8
sizeof gte = 16
gte: 0 1 111 222 10 456 123
Linux program to read data:
#include <iostream>
#include <fstream>
struct CTE {
unsigned short Version;
unsigned short Signature;
unsigned short core;
unsigned short editmode;
} __attribute__((ms_struct));
struct GTE {
unsigned char LTL : 1;
unsigned char trans : 1;
uint_least8_t wcountry;
uint_least8_t wlanguage;
unsigned int count;
int WIDTH;
int HEIGHT;
} __attribute__((ms_struct));
int main()
{
std::cout << "sizeof CTE " << sizeof(CTE) << '\n';
std::cout << "sizeof GTE " << sizeof(GTE) << '\n';
CTE cte;
std::fstream data("chopin.dat", std::ios::in | std::ios::binary);
data.read(reinterpret_cast<char*>(&cte), sizeof cte);
for(size_t i = 0; i < 11; ++i) {
GTE gte;
data.read(reinterpret_cast<char*>(>e), sizeof gte);
std::cout << +gte.LTL << ' '
<< +gte.trans << ' '
<< +gte.wcountry << ' '
<< +gte.wlanguage << ' '
<< gte.count << ' '
<< gte.WIDTH << ' '
<< gte.HEIGHT << '\n';
}
}
This produces the expected output:
sizeof CTE 8
sizeof GTE 16
0 1 111 222 1 456 123
0 1 111 222 2 456 123
0 1 111 222 3 456 123
0 1 111 222 4 456 123
0 1 111 222 5 456 123
0 1 111 222 6 456 123
0 1 111 222 7 456 123
0 1 111 222 8 456 123
0 1 111 222 9 456 123
0 1 111 222 10 456 123
0 1 111 222 10 456 123
Notice that we don't need explicitly
typedef struct _CTE_ { ... } CTE;
as C++ does that for us, for free. Also note that I'm not using
#pragma pack
on either side, but I
am using
__attribute__((ms_struct))
, and compiling with
-mms-bitfields
. Actually, I've tried with and without both, and still get the same result, so perhaps these structs are simple enough that they map perfectly well from Windows to linux without needing compiler support.
Also, be wary of using identifiers starting with an underscore. The convention is that such identifiers are reserved for the implementation, i.e. the people writing the compiler. There is a risk that something like _GTE_ could be used by the compiler or library for some internal purpose, so if one of the #included headers has the following:
#define _GTE_ 6
, then your
struct _GTE_ {}
will fail to compile. Tracking down
that mystery can take a lot of head scratching ... e.g. It compiles on OS version 7 but not on OS version 8 ... ???