Как сказал Ганс Пассан - он не всегда будет пустым.
Одно из основных свойств общих объектов c Dynami (и DLL в Windows) заключается в том, что внутренние символы библиотеки не предоставляются пользователю. В G CC это делается путем определения видимости символа по умолчанию как «скрытый» в командной строке при построении библиотеки. Однако это имеет нежелательный эффект, заключающийся в том, что все символы, включая те, которые вы хотите, чтобы пользователи вызывали, становятся скрытыми, что делает вашу библиотеку практически бесполезной.
G CC позволяет вручную управлять видимостью - __attribute__((visibility("default")))
. Это помечает функцию как имеющую видимость по умолчанию, то есть она будет предоставлена DSO. Этот атрибут указывается перед объявлением функции.
Это создает новую проблему - пользователям вашей библиотеки не нужен / не нужен этот атрибут, указанный в ваших библиотечных функциях, когда они включают ваш файл заголовка. Когда ваш заголовок включен пользователем, эти определения следует удалить, оставив только объявление функции.
Есть два способа решить эту проблему - иметь две копии вашего заголовка или использовать препроцессор для изменения кода перед компиляцией. Большинство (почти все) библиотечных программистов выбирают последнее, так как синхронизировать две копии одного и того же файла очень сложно.
Способ, которым авторы Im Gui реализовали последний вариант, довольно элегантен, а не определяя свой маркер API в строке, например:
#ifdef IMGUI_API_BUILD
#define IMGUI_API __attribute__((visibility("default")))
#else
#define IMGUI_API
#endif
Они определили его следующим образом:
#ifndef IMGUI_API
#define IMGUI_API
#endif
Это имеет эффект определения символа в значение по умолчанию, если он имеет не было отменено.
Гениальность этого на самом деле заключается в процессе компиляции - указав определение IMGUI_API
в командной строке, они могут изменить поведение кода, не подвергая элементы процесса сборки к миру.
Все, что им нужно сделать, это добавить -D IMGUI_API=__attribute((visibility("default")))
в командную строку компилятора, и файл заголовка волшебным образом помечает каждую функцию API как экспортируемую из общего объекта.
Фактически, они могут изменить определение на любое значение, которое они хотят, не раскрывая эту деталь в файле заголовка, используемом таким образом другими программистами. Информация об отладке, дополнительные параметры функций, указание информации о горячем / холодном пути ... все это можно указать в командной строке без необходимости помещать эту информацию в файл заголовка.
Изменить:
Просматривая их код сейчас, кажется, что они этого не осознали и создали очень мощное решение с разделяемой библиотекой для Linux, даже не желая этого. Несмотря на это, все вышеперечисленное остается в силе - другие библиотеки могут делать то же самое.