如何正确内联静态库

时间:2021-12-07 21:28:49

I'm re-writing a small C math library of mine that will end up as a static library for the user and would like to benefit from inlining for my vector math interface.

我正在重写我的一个小C数学库,它最终会成为用户的静态库,并希望从我的矢量数学界面的内联中受益。

I have the following:

我有以下内容:

[ mymath.h ]

[mymath.h]

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

[ mymath.c ]

[mymath.c]

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

   return v;
}

Since my library will be static and I'm only going to provide the .h (and the .lib) to the user, will the clampf function be inlined in their program when compiled?

由于我的库是静态的,我只是要向用户提供.h(和.lib),在编译时是否会在程序中内联clampf函数?

Am I doing the right thing but declaring the function extern in the .h and inline in the .c?

我做的是正确的事情但是在.h中声明了函数extern并且在.c中内联了吗?

2 个解决方案

#1


16  

You have it almost correct. You actually have it backwards; for inline functions you must put the inline definition in the header file and the extern declaration in the C file.

你几乎是正确的。你实际上倒退了;对于内联函数,您必须将内联定义放在头文件中,并将外部声明放在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 );

You have to put the definition (full body) in the header file, this will allow any file which includes the header file to be able to use the inline definition if the compiler chooses to do so.

您必须将定义(完整正文)放在头文件中,这将允许任何包含头文件的文件能够在编译器选择时使用内联定义。

You have to put the extern declaration (prototype) in the source file to tell the compiler to emit an extern version of the function in the library. This provides one place in your library for the non-inline version, so the compiler can choose between inlining the function or using the common version.

您必须将extern声明(原型)放在源文件中,以告诉编译器在库中发出该函数的外部版本。这为您的库中的非内联版本提供了一个位置,因此编译器可以在内联函数或使用通用版本之间进行选择。

Note that this may not work well with the MSVC compiler, which has very poor support in general for C (and has almost zero support for C99). For GCC, you will have to enable C99 support for old versions. Modern C compilers support this syntax by default.

请注意,这可能不适用于MSVC编译器,MSVC编译器通常对C的支持非常差(并且几乎没有支持C99)。对于GCC,您必须为旧版本启用C99支持。 Modern C编译器默认支持此语法。

Alternative:

替代方案:

You can change the header to have a static inline version,

您可以将标题更改为具有静态内联版本,

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

However, this doesn't provide a non-inline version of the function, so the compiler may be forced to create a copy of this function for each translation unit.

但是,这不提供函数的非内联版本,因此可能会强制编译器为每个转换单元创建此函数的副本。

Notes:

笔记:

  1. The C99 inlining rules are not exactly intuitive. The article "Inline functions in C" (mirror) describes them in detail. In particular, skip to the bottom and look at "Strategies for using inline functions". I prefer method #3, since GCC has been defaulting to the C99 method for a while now.

    C99内联规则并不完全直观。文章“C中的内联函数”(镜像)详细描述了它们。特别是,请跳到底部并查看“使用内联函数的策略”。我更喜欢方法#3,因为GCC已经默认为C99方法一段时间了。

  2. Technically, you never need to put extern on a function declaration (or definition), since extern is the default. I put it there for emphasis.

    从技术上讲,您永远不需要在函数声明(或定义)上放置extern,因为extern是默认值。我把它放在那里强调。

#2


6  

You should define your function as static inline in the .h file:

您应该在.h文件中将函数定义为静态内联:

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

    return v;
}

The function must be absent in the .c file.

.c文件中必须不存在该函数。

The compiler may decide not to inline the function but make it a proper function call. So every generated .o file may contain a copy of the function.

编译器可能决定不内联函数,但使其成为正确的函数调用。因此,每个生成的.o文件都可能包含该函数的副本。

#1


16  

You have it almost correct. You actually have it backwards; for inline functions you must put the inline definition in the header file and the extern declaration in the C file.

你几乎是正确的。你实际上倒退了;对于内联函数,您必须将内联定义放在头文件中,并将外部声明放在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 );

You have to put the definition (full body) in the header file, this will allow any file which includes the header file to be able to use the inline definition if the compiler chooses to do so.

您必须将定义(完整正文)放在头文件中,这将允许任何包含头文件的文件能够在编译器选择时使用内联定义。

You have to put the extern declaration (prototype) in the source file to tell the compiler to emit an extern version of the function in the library. This provides one place in your library for the non-inline version, so the compiler can choose between inlining the function or using the common version.

您必须将extern声明(原型)放在源文件中,以告诉编译器在库中发出该函数的外部版本。这为您的库中的非内联版本提供了一个位置,因此编译器可以在内联函数或使用通用版本之间进行选择。

Note that this may not work well with the MSVC compiler, which has very poor support in general for C (and has almost zero support for C99). For GCC, you will have to enable C99 support for old versions. Modern C compilers support this syntax by default.

请注意,这可能不适用于MSVC编译器,MSVC编译器通常对C的支持非常差(并且几乎没有支持C99)。对于GCC,您必须为旧版本启用C99支持。 Modern C编译器默认支持此语法。

Alternative:

替代方案:

You can change the header to have a static inline version,

您可以将标题更改为具有静态内联版本,

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

However, this doesn't provide a non-inline version of the function, so the compiler may be forced to create a copy of this function for each translation unit.

但是,这不提供函数的非内联版本,因此可能会强制编译器为每个转换单元创建此函数的副本。

Notes:

笔记:

  1. The C99 inlining rules are not exactly intuitive. The article "Inline functions in C" (mirror) describes them in detail. In particular, skip to the bottom and look at "Strategies for using inline functions". I prefer method #3, since GCC has been defaulting to the C99 method for a while now.

    C99内联规则并不完全直观。文章“C中的内联函数”(镜像)详细描述了它们。特别是,请跳到底部并查看“使用内联函数的策略”。我更喜欢方法#3,因为GCC已经默认为C99方法一段时间了。

  2. Technically, you never need to put extern on a function declaration (or definition), since extern is the default. I put it there for emphasis.

    从技术上讲,您永远不需要在函数声明(或定义)上放置extern,因为extern是默认值。我把它放在那里强调。

#2


6  

You should define your function as static inline in the .h file:

您应该在.h文件中将函数定义为静态内联:

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

    return v;
}

The function must be absent in the .c file.

.c文件中必须不存在该函数。

The compiler may decide not to inline the function but make it a proper function call. So every generated .o file may contain a copy of the function.

编译器可能决定不内联函数,但使其成为正确的函数调用。因此,每个生成的.o文件都可能包含该函数的副本。