Как правильно встроить статические библиотеки

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

У меня есть следующее:

[mymath.h]

...
...
extern float clampf( float v, float min, float max );
...
...

[mymath.c]

inline float clampf( float v, float min, float max )
{
    if( v < min ) v = min;
    if( v > max ) v = max;

   return v;
}

Так как моя библиотека будет статичной, и я только собираюсь предоставить .h.lib) пользователю, будет ли clampf функция будет встроена в их программу при компиляции?

Я правильно делаю, но объявляя функцию extern в .h и встроенный в .c?

2 ответа

Решение

У вас это почти правильно. У вас действительно есть это задом наперед; для встроенных функций вы должны поставить inline определение в заголовочном файле и extern декларация в файле C.

// mymath.h
inline float clampf( float v, float min, float max )
{
    if( v < min ) v = min;
    if( v > max ) v = max;

    return v;
}

// mymath.c
#include "mymath.h"
extern float clampf( float v, float min, float max );

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

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

Обратите внимание, что это может не работать с компилятором MSVC, который имеет очень слабую поддержку в целом для C (и практически не поддерживает C99). Для GCC вам необходимо включить поддержку C99 для старых версий. Современные компиляторы Си поддерживают этот синтаксис по умолчанию.

Альтернатива:

Вы можете изменить заголовок, чтобы иметь static inline версия,

// mymath.h
static inline float clampf(float v, float min, float max)
{
    ...
}

Однако это не обеспечивает не встроенную версию функции, поэтому компилятор может быть вынужден создать копию этой функции для каждой единицы перевода.

Заметки:

  1. Правила встраивания C99 не совсем интуитивно понятны. Статья " Встроенные функции в C" ( зеркало) описывает их подробно. В частности, перейдите к основанию и посмотрите "Стратегии использования встроенных функций". Я предпочитаю метод № 3, поскольку GCC уже некоторое время по умолчанию использует метод C99.

  2. Технически, вам никогда не нужно ставить extern в объявлении функции (или определении), так как extern по умолчанию. Я положил это там для акцента.

Вы должны определить свою функцию как static inline в.h файле:

static inline float clampf( float v, float min, float max )
{
    if( v < min ) v = min;
    if( v > max ) v = max;

    return v;
}

Функция должна отсутствовать в файле.c.

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

Другие вопросы по тегам