As flexible array members cannot to exposed to C++ (my_type fam[];
is not a valid C++ member), we'll have to define your own type.
Luckily C linkage functions don't have symbols that depend on their arguments. So we can either modify the definition of foo
within shared headers, or define our own and don't include their headers.
This is a struct
that is likely to be compatible layout-wise. Note that you should never declare these on the stack in C++:
struct foo {
int count;
#ifndef __cplusplus
my_type fam[];
#else
my_type do_not_use_fam_placeholder;
my_type* fam() {
return &do_not_use_fam_placeholder;
}
my_type const* fam() const {
return &do_not_use_fam_placeholder;
}
#endif
};
This relies upon the binary layout of the foo
structure in C to be the prefix members, followed by the flexible array member's elements, and no additional packing or alignment be done. It also requires that the flexible array member never be empty.
I would use this+1
but that runs into alignment issues if there is padding between count
and fam
.
Use of memcpy
or memmov
or the like on foo
is not advised. In general, creating a foo
on the C++ side isn't a good idea. If you have to, you could do something like this:
struct foo_header {
int count;
};
foo* create_foo_in_cpp(int count) {
std::size_t bytes = sizeof(foo)+sizeof(my_type)*(count-1);
foo* r = (foo*)malloc(bytes);
::new((void*)r) foo_header{count};
for (int i = 0; i < count; ++i)
::new( (void*)(r->fam()+i) my_type();
return r;
};
which constructs every object in question in C++. C++'s object existence rules are more strict than C's; merely taking some POD memory and interpreting it as a POD is not a valid action in C++, while it is in C. The new
s above will be optimized to noops at runtime, but are required by C++ to declare that the memory in question should be treated as objects of that type under strict reading of the standard.
Now, there are some standard issues (defects) with manually per-element constructing the elements of an array, and layout-compatibility between arrays and elements, so you'll have to trust somewhat that the ABI of the C++ compiler and the C code is compatible (or check it).
In general, all interop between C and C++ is undefined by the C++ standard (other than some parts of the standard C library which C++ incorporates; even here, there is no mandate that C++ use the same C library). You must understand how your particular implementation of C and C++ interoprate.