【发布时间】:2012-12-31 14:02:31
【问题描述】:
我有一个 C++11 应用程序代码使用的 C99 代码实用程序库。一些内联函数以 C99 风格声明,并在翻译单元中显式生成代码,例如:
// buffer.h
inline bool has_remaining(void* obj) {
...
}
// buffer.c
extern inline bool has_remaining(void * obj);
但是,当我尝试在 C++ 应用程序中使用 has_remaining 时,我在链接时收到有关多个定义的错误。尽管有 extern "C" header guards 说明符,g++ 似乎正在实例化库中已经存在的内联代码。
有没有办法强制 g++ 使用这种类型的定义?
看起来如果我 #ifdef __cplusplus 一个带有 gnu_inline 属性的外部定义,正确的事情将会发生,但肯定有一种更便携的方法来保持现代 C 头文件与现代 C++ 兼容?
-- 编辑:工作示例--
buffer.h:
#ifndef BUFF_H
#define BUFF_H
#include <stdbool.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
inline bool has_remaining(void const* const obj) {
return (obj != NULL);
}
#ifdef __cplusplus
}
#endif
#endif /* BUFF_H */
buffer.c:
#include "buffer.h"
extern inline bool has_remaining(void const* const obj);
app.cpp:
#include <stdlib.h>
#include <stdio.h>
#include "buffer.h"
int main(int argc, char** argv) {
char const* str = "okay";
printf(str);
has_remaining(str);
return (0);
}
编译:
$ gcc -std=gnu99 -o buffer.o -c buffer.c
$ g++ -std=gnu++11 -o app.o -c app.cpp
$ g++ -Wl,--subsystem,console -o app.exe app.o buffer.o
buffer.o:buffer.c:(.text+0x0): multiple definition of `has_remaining'
app.o:app.cpp:(.text$has_remaining[_has_remaining]+0x0): first defined here
collect2.exe: error: ld returned 1 exit status
--编辑 2--
__gnu_inline__ 属性确实解决了多个定义的问题。我仍然希望看到一种(更)可移植的方法或一些决定性的推理为什么不存在。
#if defined(__cplusplus) && defined(NOTBROKEN)
#define EXTERN_INLINE extern inline __attribute__((__gnu_inline__))
#else
#define EXTERN_INLINE inline
#endif
EXTERN_INLINE bool has_remaining(void const* const obj) {
return (obj != NULL);
}
【问题讨论】:
-
为什么要有
extern声明?包含没有它的标题不起作用? -
extern "C"和标头保护无关。为什么在.c文件中声明extern inline(呵呵)函数...? -
我不太确定如何调用 #ifdef __cplusplus 块来保护 C-mangled 函数(如果不是“标题保护”)。有关 extern inline 的说明,请参阅此处,greenend.org.uk/rjk/tech/inline.html——它强制编译器在特定的翻译单元中发出符号。
-
但是标准解决方案呢:定义任何预处理器常量并使用#ifdef 使每个 C++ 文件包含的 buffer.h 不超过 1 次?
-
我没有看到多个定义。在 C++ 中,它们很弱,并被链接器合并。这是什么平台?您有完整的简短示例,以便我们重现它吗?