Привет. Появился вопрос по __inline. Скорее всего решения нету, но вдруг я чего-то не вижу. Код - чистый Си, без плюсов. Пишется библиотека для работы с определённым типом файлов. И в эти файлы надо писать различные сигнатуры. Функция выглядит примерно так: Код (Text): void write_sign1(FILE *f) { putc(char1,f); putc(char2,f); } Таких функций много. Поэтому хотел сделать инлайн. И тут появляется проблема - где писать тело этих функций. Если писать в *.С файле, который потом компилируется в lib - то эти функции наружу вообще не видны, что понятно. А если писать в заголовочном файле - то на первый взгляд всё отлично. Но если по каким-то причинам компилятор откажется инлайнить, полезут сообщения от линкера что функция объявлена много раз. Потому что заголовочный файл включается в несколько файлов приложения, использующего библиотеку. Пока кроме макроса ничего придумать не могу. Может кто чего подскажет? Вообще основной вопрос - можно ли заставить компилятор инлайнить функцию, объявленную в другом файле.
И чего? Ты проблему не понял. Вот тебе пример что это не поможет: Код (Text): // Header.h #ifndef _FILENAME_H_ #define _FILENAME_H_ void __inline write_sign(FILE *f) { putc(123,f); } #endif Код (Text): // App_src1.c #include<Header.h> // some code here Код (Text): // App_src2.c #include<Header.h> // some code here Теперь компилируем эти два исходника (App_src1.c и App_src2.c) и собираем в приложение. Компилируются они отдельно, и код из Header.h будет подставлен в оба. А теперь при сборке линкер честно на тебя будет кричать - есть несколько функций с одинаковым именем.
а где инлайн? Как правило инлайны и вставляют в хидеры. Что б твой пример заработал (хотя это очень корявый пример, и лучше никогда не помещать код в хидеры) необходимо добвать static в объявлении.
Пропустил. Исправил сообщение. Проблема в том, что __inline это просто рекомендация. И если компилятор всё равно решит не инлайнить, то будут повторные реализации. А static не вариант - всё равно будет куча версий одной функции. Y_Mur - нашёл такой ключ только в 2008 студии...
cppasm как вариант можно попробовать 2008 линкер использовать совместно с другими компиляторами, правда там пишут что этот ключ заставляет линкер повторно вызывать компилятор для совместной работы.
Не ругется, что я делаю не так? Код (Text): test.h: void __inline write_sign(FILE *f) { putc('t', f); } test2.c: #include <stdio.h> #include "test.h" extern "C" void test_func(FILE *f); int __cdecl main(int argc, char* argv[]) { test_func(stdout); write_sign(stdout); getchar(); return 0; } test1.c: #include <stdio.h> #include "test.h" void test_func(FILE *f) { write_sign(f); } Решит/не решит это еще не ясно. Скорее всего всё будет работать корректно. но зато они не будут торчать наружу.
Так и у меня не ругается. И не будет, до тех пор, пока компилятор будет послушно инлайнить. Так вот именно, что зависит от фазы луны. __inline не гарантирует что фукция будет встроена. А если она встроена не будет - полезут ошибки. Это да.
Теоретически должны. Потому что реализация функции из заголовочного файла попадёт в каждый *.с, и будет дублирование имён на этапе сборки. В общем на всякий пожарный случай добавил к __inline ещё static - на случай если inline будет проигнорирован. На этом и остановлюсь наверное. Т.е. если __inline отработает, то всё нормально. А если нет - то функция будет продублирована в каждом модуле, но она будет внутренней. Немного не оптимально в плане размера, но это по сути редкий случай. А вообще компилятор умный зануда Вообще всё работает даже и без static. Можно насильно указать опцию /Ob0 - никакого инлайна (для проверки что будет). Так вот что интересно. Функция дублируется в каждый *.obj. Я смотрел список имён при помощи objconv.exe Агнера Фога. Во всех модулях она имеет одно и то же имя и атрибут public - т.е. торчит наружу. От cdecl функций ничем не отличается (в плане атрибутов в объектнике). Но линкер на неё не ругается. Почему - я так и не нашёл.
По стандартам ошибок быть не должно даже без static. Цитата из C99: Несколько внешних определений запрещено. Несколько инлайн-определений - пожалуйста.
Да, но это в С99 - там ввели ключевое слово inline. Я в С89 компилирую, а там стандарт ничего не оговаривает. По старту С89 вообще нету __inline - это расширение, хотя и поддерживается практически всеми компиляторами. Но судя по тестам поведение аналогичное, просто в С99 его узаконили. Да что ты говоришь? И часто ты *.h файлы компилируешь? Заголовочный *.h подключается в *.c, его код просто подставляется препроцессором в *.c файл. И компилируется именно *.c файл. И если их много в проекте - в каждом будет реализация функции. Не веришь - возьми и проверь хотя бы мой пример без __inline: Код (Text): // Header.h #ifndef _SIGN_H_ #define _SIGN_H_ void write_sign(FILE *f) { putc(123,f); } #endif Код (Text): // Sign1.c #include<stdio.h> #include<Header.h> void print(void); int main(void) { FILE *f; f=fopen("out.bin","wb"); if(!f) return 1; write_sign(f); print(); fclose(f); return 0; } Код (Text): // Sign2.c #include<stdio.h> #include<Header.h> void print(void) { printf("Hello from Sign2 source.\n"); } cl /Ox /I"." Sign1.c Sign2.c И посмотри что тебе линкер скажет. А функция реализована в одном *.h