C在C++中超出标头
C out of header in C++
如果我在C++环境中使用C代码,并且我将所有代码都包含在头中,那么一切都很好。如果我试图在头中声明C函数,并且它们在.C或.cpp文件中实现它们,我会得到以下错误:
Undefined symbols for architecture x86_64:
"vec2_norm(Vec2)", referenced from:
_main in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Vec2.h
#ifndef Physics_Engine_Test_Vec2_h
#define Physics_Engine_Test_Vec2_h
typedef struct
{
float x;
float y;
} Vec2;
inline Vec2 vec2_norm(Vec2 v);
#endif
Vec2.c或.cpp
#include "Vec2.h"
#include <math.h>
inline Vec2 vec2_norm(Vec2 v) {
float len = v.x*v.x + v.y*v.y;
if (len) {
len = 1 / sqrtf(len);
v.x *= len;
v.y *= len;
}
return v;
}
尽管我测试了您的代码示例,并且它使用g++/gcc和clang++/crang对我来说编译得很好,但当您想要编译基于C的源代码时,最好在它周围添加extern "C" {}
,这样编译器就不会对这些函数进行C++名称篡改:
#ifdef __cplusplus
extern "C" {
#endif
typedef struct
{
float x;
float y;
} Vec2;
inline Vec2 vec2_norm(Vec2 v);
#ifdef __cplusplus
};
#endif
和
extern "C" {
inline Vec2 vec2_norm(Vec2 v) {
float len = v.x*v.x + v.y*v.y;
if (len) {
len = 1 / sqrtf(len);
v.x *= len;
v.y *= len;
}
return v;
}
};
顺便说一句,关于您在代码中使用的inline
,尽管仅在标头中定义内联函数不是强制性的,但强烈建议您这样做,这样您就不必将内联正文复制到每个包含该标头的翻译单元,因为一个定义规则。
正如维基百科在这个话题上所说:
有些东西,如类型、模板和外部内联函数,可以在多个翻译单元中定义。对于给定的实体,每个定义必须相同。不同翻译单元中的非外部对象和函数是不同的实体,即使它们的名称和类型相同。
但最终,这是一个好主意还是坏主意取决于你的设计选择。
HTH
这里实际上有两个错误:
-
如果在内联中声明一个函数,则除非在给定的编译单元中需要,否则不会对其进行编译。所以Vec2.o文件不会包含它,链接器也找不到它。内联函数总是必须放在头中,所以编译器在每个需要它的编译单元中都可以看到它们的实现。
-
正如H2CO3所说,C++使用名称篡改:它将参数类型编码到函数名称中,以允许重载。C不这么做。因此,如果您编译一个使用您的函数的c++文件,它将希望链接到某个奇怪的名称,而不仅仅是"vec2_norm"。为了能够将C代码链接到C++代码中,您必须告诉编译器它应该使用C符号名称。
大多数情况下,人们通过编写以下形式的标题来做到这一点:
#ifdef __cplusplus
extern "C" {
#endif
Vec2 vec2_norm(Vec2 v);
#ifdef __cplusplus
}
#endif
顺便问一下,有人知道如何在stackoverflow中正确格式化预处理器指令吗?
- 如何在音频处理中使用超能力时间拉伸类
- 我的超类中的模板问题与结构定义
- 在具有 MPI 的超立方体中广播
- 在 c++ 中调用超构造函数之前做一些事情
- 我们可以在没有新实例化的情况下声明一个抽象方法来返回抽象超类中的子类对象吗
- C++为API中定义的结构创建超类
- 确保指向超类的指针指向c++中某个子类的对象
- 如何将超类的受保护成员访问到其派生类. 如果已在派生类中声明了具有相同名称的函数?
- C++:从类型索引中获取超类类型索引
- 如何将项目放入具有模板化超类类型的向量中
- QT 中的串行通信超时与 Arduino
- C++ 如何使用一个参数从派生类构造函数中调用具有两个参数的超类构造函数
- 如何在接口类中创建一个超类对象
- 如何在 c++ 中从模板基类的构造函数调用模板超类的构造函数?
- 子类是否也在 c++ 中继承私有数据成员?但通过超类的公共方法访问
- 如何在opencv C++中访问特定的超像素
- 在子类函数中访问超类友元的受保护数据成员
- 尝试在构造函数中超限时间
- 更改所有子类中超类变量的值
- 如何在C++中超类某些数据结构