Есть ли веская причина для #include исходные (* .c * .cpp) файлы? - PullRequest
1 голос
/ 12 июля 2010

Я некоторое время работал с библиотекой с открытым исходным кодом (« быстрая искусственная нейронная сеть »). Я использую его источник в моей статической библиотеке. Однако, когда я его компилирую, я получаю сотни предупреждений компоновщика, которые, вероятно, вызваны тем фактом, что библиотека включает файлы * .c в другие файлы * .c (поскольку я включаю только некоторые заголовки, которые мне нужны, и я не трогал код самой библиотеки).

Мой вопрос: есть ли веская причина, по которой разработчики библиотеки использовали этот подход, который настоятельно не рекомендуется? (Или, по крайней мере, мне всю жизнь говорили, что это плохо, и из собственного опыта я считаю, что это плохо). Или это просто плохой дизайн и в этом подходе нет выгоды?

Я знаю этот связанный вопрос , но он не отвечает на мой вопрос. Я ищу причины, которые могли бы оправдать это.

Дополнительный вопрос: есть ли способ, как это исправить, не слишком касаясь кода библиотеки? У меня много собственной работы, и я не хочу создавать больше;)

Ответы [ 6 ]

3 голосов
/ 12 июля 2010

Насколько я вижу (grep '#include .*\.c'), они делают это только в файлах doublefann.c, fixedfann.c и floatfann.c и каждый раз включают причину:

/* Easy way to allow for build of multiple binaries */

Такое точное использование препроцессора для простого вставки копий действительно является единственным допустимым использованием включающих файлы реализации (* .c) и является относительно редким. (Если вы хотите включить некоторый код по другой причине, просто дайте ему другое имя, например * .h или * .inc.) Альтернативой является указание конфигурации в макросах, передаваемых компилятору (например, -DFANN_DOUBLE, -DFANN_FIXED или -DFANN_FLOAT), но они не использовали этот метод. (У каждого подхода есть свои недостатки, поэтому я не говорю, что они обязательно ошибочны, мне нужно детально изучить этот проект).

Они предоставляют make-файлы и проекты MSVS, которые уже не должны связывать doublefann.o (из doublefann.c) с fann.o (из fann.c) или fixedfann.o (из fixedfann.c) и так далее, либо их файлы испорчены, либо что-то подобное пошло не так.

Вы пытались создать проект с нуля (или использовать существующий проект) и добавить в него все файлы? Если вы это сделали, то происходит то, что каждый файл реализации компилируется независимо, а результирующие объектные файлы содержат противоречивые определения. Это стандартный способ работы с файлами реализации, и многие инструменты предполагают это. Единственное возможное решение состоит в том, чтобы исправить настройки проекта, чтобы не связывать их вместе. (Хорошо, вы могли бы также радикально изменить их источник, но это не совсем решение.)

Пока вы занимаетесь этим, если вы продолжите без использования настроек проекта, вы, вероятно, можете пропустить компиляцию fann.c, et. и др. и, возможно, достаточно просто удалить их из проекта & ndash; тогда они не будут скомпилированы и связаны. Вы захотите выбрать точно один из double- / fixed- / floatfann для использования, в противном случае вы получите те же ошибки ссылки. (Я не смотрел на их инструкции, но не удивлюсь, если это резюме будет объяснено более подробно.)

2 голосов
/ 12 июля 2010

Включение кода C / C ++ приводит к тому, что весь код склеивается в одном блоке перевода. С хорошим компилятором это может привести к значительному увеличению скорости (так как вещи могут быть встроены, а вызовы функций оптимизированы).

Если фактический код будет включен таким образом, он должен иметь static в большинстве своих объявлений, иначе он вызовет предупреждения, которые вы видите.

0 голосов
/ 12 июля 2010

Сейчас я занимаюсь этим дома, потому что я относительно новичок в C ++ для Linux и не хочу увязать в трудностях с компоновщиком. Но я бы не рекомендовал это для правильной работы.

(мне также однажды пришлось включить header.dat в программу на C ++, потому что Rational Rose не позволял заголовкам быть частью выпущенного программного обеспечения, и нам нужен был этот конкретный исходный файл в работающей системе (по непонятным причинам) .)

0 голосов
/ 12 июля 2010

Я не смотрел код, но возможно, что включаемые файлы .c или .cpp на самом деле содержат код, который работает в заголовке.Например, шаблон или встроенная функция.Если это так, то предупреждения будут ложными.

0 голосов
/ 12 июля 2010

Я не знаю эту библиотеку, но, как вы ее описываете, это либо плохая практика, либо ваше понимание того, как ее использовать, недостаточно хорошо.

Проект C, который хочет включить другие, должен всегда предоставлять хорошо структурированные .h файлы для других, а затем скомпилированную библиотеку для компоновки. Если он хочет включить определения функций в заголовочные файлы, он должен пометить их как static (по старинке) или как inline (возможно, начиная с C99).

0 голосов
/ 12 июля 2010

Если вы когда-нибудь объявите одну глобальную переменную или функцию в этом файле .c, она не может быть включена в два места, которые оба компилируются в один и тот же двоичный файл, или два определения столкнутся. Если он включен хотя бы в одном месте, он также не может быть скомпилирован сам по себе, но все еще связан с тем же двоичным файлом, что и его пользователь.

Если файл включен только в одном месте, почему бы просто не сделать его дискретным модулем компиляции (и использовать его глобальные переменные через объявления extern)? Зачем вообще его включать?

Если ваши C-файлы не объявляют глобальные переменные или функции, они являются заголовочными файлами и должны быть названы так.

Следовательно, с помощью исчерпывающего поиска я могу сказать, что единственный раз, когда вы потенциально захотите включить C-файлы, это единственный случай, когда один и тот же C-код используется при создании нескольких различных двоичных файлов. И даже там вы увеличиваете время компиляции без реальной выгоды.

Это предполагает, что функции, которые должны быть встроены, помечены inline, и что у вас есть достойный компилятор и компоновщик.

Я не знаю, как быстро это исправить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...