Reputation: 3052
2 struct
s came from different header files from different libraries. The libraries have a lot of similar stuff.
How can I ensure that the memory layout of them are binary compatible? In addition how can I check the naming of them are equal? The checking should be done at compile time.
As an example:
//Header of Library A
namespace LibA {
struct Item {
uint32_t A;
uint8_t B;
uint8_t pad1,pad2,pad3;
};
void FunctionOfLibA(Item *a);
}
//Header of Library B
namespace LibB {
struct Item {
uint32_t A;
uint8_t B;
uint8_t pad1,pad2,pad3;
};
void FunctionOfLibB(Item *a);
}
//My Usage
LibA::Item item;
LibA::FunctionOfLibA(&item);
LibB::FunctionOfLibB((LibB::Item*)(void*)(&item)); //I want to check if this cast is safe.
//So I have to ensure the alignment, pack, order etc. are the same for both LibB::Item and LibA::Item
Ok - in the above example it's easy to do it the manual way with sizeof(...)
and offsetof(...)
. As an alternative I Can manually check the header files for each new library version.
But the question is to do it in an automatic way like static_assert(issame(LibA::Item,LibB::Item),"Check")
?
Upvotes: 4
Views: 502
Reputation: 41805
In C++20 there are the layout-compatibility and pointer-interconvertibility traits so you can do it with std::is_layout_compatible
static_assert(std::is_layout_compatible_v<LibA::Item, LibB::Item>, "Check")
Note that it may not work if the structs aren't standard-layout, or using non-compatible types, for example if one uses signed char
/unsigned char
and the other uses char
(when char
is signed/unsigned on that platform respectively) then they're incompatible
If your C++ version is older than that, sorry you'll have to upgrade or find another way, like modifying the 2 libraries or manually using sizeof
and offsetof
. However if you don't need portability then on some compilers you can try to use their intrinsics, for example __is_layout_compatible
on GCC 12+
Upvotes: 2