C++代码链接出错:警告C4190:type指定了C-linkage,但返回与C不兼容的UDT

kin*_*kin 6 c c++ dll

我很难理解为什么以下代码(带有标准布局的UDT)在visual C++ 2012中给出了C-linkage警告:

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
}
Run Code Online (Sandbox Code Playgroud)

函数的定义在C++文件中:

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);
}
Run Code Online (Sandbox Code Playgroud)

Pau*_*and 8

原因是当您使用C++编译器编译该代码时,预处理的代码如下所示:

typedef struct vec3 {
    float   x;
    float   y;
    float   z;
    vec3(float x, float y, float z) : x(x), y(y), z(z) {}
} vec3;

extern "C" {
vec3    vec3_add(vec3 a, vec3 b);
}
Run Code Online (Sandbox Code Playgroud)

所以编译器看到的函数'vec3_add'被声明为具有C链接,但使用类型'vec3',它具有C编译器无法理解的构造函数.C++编译器不知道C编译器不会看到构造函数,因此会发出警告.请记住,预处理在编译之前发生,因此在#ifdef __cplusplus报告警告时编译器看不到这些行.

这类问题的常见模式是:

extern "C" {

typedef struct vec3 {
    float   x;
    float   y;
    float   z;
} vec3;

vec3 vec3_add(vec3 a, vec3 b);

}

#ifdef __cplusplus

struct CVec3 :vec3 {
    CVec3(float X, float Y, float Z) { x = X; y = Y; z = Z; }
};

#endif
Run Code Online (Sandbox Code Playgroud)

这样,在调用'vec3_add'时,C++代码可以使用'CVec3'类型而不是'vec3'类型.C代码只能看到'vec3'POD类型.


gre*_*g_p -1

我相信你需要在 cxx 文件中再次声明 vec3_add 是一个 C 链接函数:

extern "C" 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);
}
Run Code Online (Sandbox Code Playgroud)