C++代码链接中的错误:警告 C4190:类型指定了 C 链接,但返回与 C 不兼容的 UDT
Error in C++ code linkage: warning C4190: type has C-linkage specified, but returns UDT which is incompatible with C
我很难理解为什么以下代码(具有标准布局的UDT)在Visual C++ 2012中给出C链接警告:
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
}
函数的定义位于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);
}
原因是当您使用 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);
}
因此,编译器看到的是声明为具有 C 链接的函数 'vec3_add',但使用类型 '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
这样,C++代码可以在调用"vec3_add"时使用"CVec3"类型而不是"vec3"类型。C 代码将只看到"vec3"POD 类型。
错误消息非常清楚;当您使用extern "C"
时,您只能使用与 C ABI 兼容的代码。非 POD 结构(例如,具有用户定义构造函数的结构)与 C ABI 不兼容。
您应该从结构定义中删除它:
#ifdef __cplusplus
vec3(float x, float y, float z) : x(x), y(y), z(z) {}
#endif
无论如何,它都可能导致未定义的行为,因为添加它可能会导致结构布局发生变化。 如果您希望能够在C++代码中整齐地构造vec3
,请编写一个函数来执行此操作,例如
vec3 make_vec3(float x, float y, float z) { vec3 v; v.x=x; v.y=y; v.z.z; return v; }
此外,您应该将整个标头包装在extern "C"
中(其中包含的标准标头除外),而不仅仅是其中的零碎部分。
我相信您需要在 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);
}
相关文章:
- 返回的指向C++对象的链接是什么样的
- 返回一个带有 std::move 的对象并链接函数
- 我的动态链接队列在同一输出流中调用时不正确地输出三个返回函数
- 从两个 lambda 的函数返回 lambda 时的链接器错误
- 在索引中插入节点:链接列表未正确返回列表
- 从函数中的指针返回对象,例如链接列表
- 为什么 VS C++链接器返回具有混合 DLL 转发的"LNK2001: unresolved external symbol"?
- 如何返回指向链接列表中最大值的指针
- C++链接列表头返回 NULL,即使列表不为空
- 在对类对象的赋值进行链接时获取垃圾值,使用按值返回类对象的赋值运算符重载
- 返回值上的 C++ 方法链接不起作用
- C++ 链接器错误未定义对"Suma(int, int)"的引用 ld 返回 1 个退出状态
- 链接错误:收集 2:错误:ld 返回 1 个退出状态
- 尽管返回了引用,但无法链接重载的赋值运算符
- 链接错误(collect2:ld返回1)
- 链接列表中的虚函数 - 多种返回类型(对象)
- 通过参考和操作员链接返回
- 链接不返回对象的运算符
- 方法调用链接;返回指针与引用
- Boost::filesystem::is_empty()对于符号链接返回false