我有一个C ++代码使用的C99代码实用程序库。一些内联函数以C99样式声明,并在转换单元中明确生成代码,如:
// buffer.h
inline bool has_remaining(void* obj) {
...
}
// buffer.c
extern inline bool has_remaining(void * obj);
但是,当我尝试在C ++应用程序中使用has_remaining
时,我会在链接时收到有关多个定义的错误。似乎g ++正在实例化库中已存在的内联代码,尽管extern "C"
标题保护说明符。
有没有办法强制g ++使用这种类型的定义?
如果我#ifdef __cplusplus
具有gnu_inline
属性的外部定义,那么正确的事情就会发生,但是肯定有一种更便携的方式来保持现代C头与现代C ++兼容吗? / p>
- 编辑:工作示例 -
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);
}
答案 0 :(得分:0)
C ++ 11标准状态(3.2.3),即:
每个程序应该只包含该程序中使用的每个非内联函数或变量的一个定义;无需诊断。该定义可以在程序中明确显示,可以在标准或用户定义的库中找到,或者(在适当的时候)隐式定义(见12.1,12.4和12.8)。 内联函数应在每个使用它的翻译单元中定义。
C ++也知道extern + inline,但将其理解为“具有外部链接的内联函数在所有翻译单元中应具有相同的地址”(7.1.2)
所以extern + inline就像你使用它一样是纯粹的C99功能,你必须有足够的东西来制作类似的东西:
#ifdef __cplusplus
#define C99_PROTOTYPE(x)
#else
#define C99_PROTOTYPE(x) x
#endif
请参考buffer.c:
// buffer.c
C99_PROTOTYPE(extern inline bool has_remaining(void * obj);)
C ++ 11标题中的内联函数是可以的,如果没有C99风格的原型,它应该可以正常工作。
答案 1 :(得分:0)
将static
与inline
一起使用可以修复“多个定义”问题。即使对于不能自己决定它不应该为'内联函数生成符号的编译器。
答案 2 :(得分:0)
这是向gcc报告的: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56066 经过讨论从这里开始: http://gcc.gnu.org/ml/gcc-help/2013-01/msg00152.html
在linux上,gcc为内联函数发出弱符号,为extern内联函数发出强符号。在链接时,弱的被丢弃而有利于强者。显然,在Windows上,事情的处理方式不同。我对Windows没有任何经验,所以我不知道那里发生了什么。