I am having a hard time understanding why the following code (UDT with standard layout) gives a C-linkage warning in visual C++ 2012:
warning C4190: 'vec3_add' has C-linkage specified, but returns UDT 'vec3' which is incompatible with C
typedef struct vec3 {
float x;
float y;
float z;
#ifdef __cplusplus
vec3(float x, float y, float z) : x(x), y(y), z(z) {}
#endif
} vec3;
#ifdef __cplusplus
extern "C" {
#endif
vec3 vec3_add(vec3 a, vec3 b);
#ifdef __cplusplus
}
The definition of the function is in a C++ file:
vec3
vec3_add(vec3 a, vec3 b) {
static_assert(std::is_standard_layout<vec3>::value == true, "incompatible vec3 type");
return vec3(a.x + b.x, a.y + b.y, a.z + b.z);
}
The reason is when you compile that code with a C++ compiler, the preprocessed code looks like this:
So what the compiler sees is the function 'vec3_add' declared as having C linkage, but using the type 'vec3' which has as a constructor which a C compiler won't understand. The C++ compiler doesn't know that a C compiler won't see the constructor so emits the warning. Remember, preprocessing happens before compilation, so the
#ifdef __cplusplus
lines are not visible to the compiler at the time when the warning is reported.A common pattern for this sort of issue is:
In this way, C++ code can use the 'CVec3' type instead of the 'vec3' type in calls to 'vec3_add'. C code will only see the 'vec3' POD type.
The error message is pretty clear; when you are using
extern "C"
you can only use code that is compatible with the C ABI. Non-POD structs (e.g. struct with a user-defined constructor) is not compatible with the C ABI.You should remove this from the struct definition:
It probably causes undefined behaviour having it there anyway, since adding this in may cause the struct layout to change. If you want to be able to tidily construct a
vec3
in C++ code then write a function to do so, e.g.Also you should wrap the entire header in
extern "C"
(except for standard headers included from it), not just bits and pieces of it.I believe you need to state again in the cxx file that vec3_add is a C linkage function: