Совместимые определения встроенных функций для C99 и переполнения стека

У меня есть служебная библиотека кода C99, используемая кодом приложения C ++ 11. Несколько встроенных функций объявлены в стиле C99 с кодом, явно сгенерированным в модуле перевода, например:

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

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

Тем не менее, когда я пытаюсь использовать has_remaining в приложении C ++ я получаю ошибки о нескольких определениях во время ссылки. Кажется, что g ++ создает экземпляр встроенного кода, который уже существует в библиотеке, несмотря на extern "C" охранники спецификатор.

Есть ли способ заставить 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);
}

3

Решение

Об этом сообщили в gcc:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56066
после обсуждения, начинающегося здесь:
http://gcc.gnu.org/ml/gcc-help/2013-01/msg00152.html

В Linux gcc испускает слабые символы для встроенных функций и сильный символ для внешних встроенных. Во время соединения слабые отбрасываются в пользу сильного. Видимо, на окнах все обрабатывается по-разному. У меня нет опыта работы с окнами, поэтому я не могу сказать, что там происходит.

0

Другие решения

Стандарт C ++ 11 утверждает (3.2.3), что:

Каждая программа должна содержать ровно одно определение каждой не встроенной функции или переменной, которая используется в этой программе в виде odr; Диагностика не требуется. Определение может явным образом появиться в программе, оно может быть найдено в стандартной или пользовательской библиотеке или (при необходимости) неявно определено (см. 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

И обратитесь в buffer.c:

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

встроенная функция в заголовке для C ++ 11 в порядке и должна работать без прототипов в стиле C99.

0

С помощью static с inline должен решить проблему с «множественными определениями». Даже для компилятора, который сам не может решить, что он не должен генерировать символы для «встроенных» функций.

0
По вопросам рекламы [email protected]