C++ C99和C+的内联函数的兼容定义+;

C++ C99和C+的内联函数的兼容定义+;,c++,c,gcc,c++11,c99,C++,C,Gcc,C++11,C99,我有一个C++11应用程序代码使用的C99代码实用程序库。一些内联函数以C99样式声明,代码在翻译单元中显式生成,如: // buffer.h inline bool has_remaining(void* obj) { ... } // buffer.c extern inline bool has_remaining(void * obj); 但是,当我尝试在C++应用程序中使用 HasyTrime时,我会在链接时得到关于多个定义的错误。似乎g++正在实例化库中已经存在的内联代码,尽管有

我有一个C++11应用程序代码使用的C99代码实用程序库。一些内联函数以C99样式声明,代码在翻译单元中显式生成,如:

// buffer.h
inline bool has_remaining(void* obj) {
...
}

// buffer.c
extern inline bool has_remaining(void * obj);

但是,当我尝试在C++应用程序中使用<代码> HasyTrime时,我会在链接时得到关于多个定义的错误。似乎g++正在实例化库中已经存在的内联代码,尽管有

extern“C”
头保护说明符

有没有办法强迫g++使用这种类型的定义

看起来,如果我用<代码> GnuiInLe> <代码>属性定义一个外部定义,正确的事情就会发生,但是肯定有一种更便携的方法来保持现代C标题与现代C++(?)/P>兼容。 --编辑:工作示例--

缓冲区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 */
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);
}
--编辑2--
属性确实解决了多个定义的问题。我仍然希望看到一个(更)可移植的方法或一些结论性的推理,为什么一个方法不存在

#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);
}
C++11标准规定(3.2.3),即:

每个程序应仅包含该程序中使用的每个非内联函数或变量的一个定义;无需诊断。定义可以显式出现在程序中,可以在标准或用户定义库中找到,或者(在适当情况下)隐式定义(见12.1、12.4和12.8)应在使用odr的每个翻译单元中定义内联函数。

C++也知道extern+inline,但理解为“带有外部链接的内联函数在所有翻译单元中应具有相同的地址”(7.1.2)

因此,使用extern+inline时,它是纯C99特性,必须有足够的功能使您能够制作如下内容:

#ifdef __cplusplus
#define C99_PROTOTYPE(x)
#else
#define C99_PROTOTYPE(x) x
#endif
并参考缓冲区c:

// buffer.c
C99_PROTOTYPE(extern inline bool has_remaining(void * obj);)

C++11的头文件中的内联函数正常,如果没有C99样式的原型,应该可以正常工作。

使用
static
inline
可以解决“多定义”问题。即使对于不能自行决定不应为“内联”函数生成符号的编译器来说。

这是向gcc报告的: 在这里开始讨论之后:


在linux上,gcc为内联函数发出弱符号,为外部内联函数发出强符号。在连接时,弱者被丢弃,取而代之的是强者。显然,在windows上,事情的处理方式不同。我对windows没有任何经验,因此我无法判断那里发生了什么。

为什么要使用
extern
声明?包括没有它的收割台将无法工作?
extern“C”
和收割台防护装置无关。为什么要在
.c
文件中使用
外部内联
(huh)函数声明…?我不太确定如果不是“头保护”,如何调用保护c-mangled函数的#ifdef uu cplusplus块。为了解释外部内联,请参见这里,它强制编译器在特定的翻译单元中发射符号。但是标准解决方案:定义任何预处理器常数,使用“yfIFDEF”不包括缓冲区。H每个C++文件的时间超过1次?我没有看到多个定义。在C++中,那些是弱的,并被链接器合并。这是什么站台?你有完整的简短示例让我们重现吗?g++从不解析buffer.c。编辑中的工作示例可能有助于解释这一点。不同意。尝试
g++test.c-S--verbose
,您将看到为源代码调用了cc1plus。对于GCC,正确的语法是“代码> GCC -X C++测试。C—VBBOSE < /COD> Windows在其对象文件中没有“弱符号”支持(或者至少它没有在GNU工具中实现)。这是一个在C语言和C++语言范围之外的特性,因此定义了实现。在Windows上处理C++内联函数是如何合并的?我想您会得到符号的多重错误。但是我不知道
\uu gnu\u inline\uu
是如何工作的。一般来说,GnuiNILN允许C89代码与C99外部内联一起工作,使定义仅用于内联,防止生成符号。我正在查看C++对象的ObjDIP-X输出,我注意到有内联函数的单独部分。它似乎用COMDAT字段值4进行注释。根据图像_COMDAT _SELECT _EXACT _MATCH对应的值4:“链接器在该符号的定义中选择任意部分。如果所有定义都不完全匹配,则会发出多重定义符号错误。”C99符号没有COMDAT选择字段。
#ifdef __cplusplus
#define C99_PROTOTYPE(x)
#else
#define C99_PROTOTYPE(x) x
#endif
// buffer.c
C99_PROTOTYPE(extern inline bool has_remaining(void * obj);)