4

Following from this question I asked before. I want to know how could I define an inline function in global scope.

I want to declare inline function in test.h, define it in main.c and call it from test.c.

main.c and test.c both #include "test.h" (for code sample please click the link above).

This is basiclly some sort of callback function that user can enable/disable. And only one file should have the function defined.

I know inline is just a suggestion to the compiler and it doesnt make much difference on modern CPUs but this is for 8-bit microcontroller and would really need it.

EDIT:

I have a function in test.c which calls this inlined function. I just want to replace the call with the body of function defined in main.c. I hope that makes sense.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
user1806687
  • 934
  • 1
  • 10
  • 27

4 Answers4

3

Most 8-bit microcontroller code is written in language that approximates C89 (there are often extensions, e.g. inline assembly), and inline was not officially part of C until C99. So first of all identify what standard you are compiling for (if any) and consult your compiler manual if inline is an extension (i.e. not C99 inline). Compiler manuals take precedence over C standards in that realm of programming.

Per C99 If both main.c and test.c both need to call the same function AND it needs to be marked inline, then I believe it MUST be defined in the header because an inline function cannot span translation units (i.e. ".c" files).

For example:

test.h:

static inline int add(int a, int b) { return a + b; }

main.c:

#include "test.h"
void main(void)
{
   int x = add(10,15);
}

test.c:

#include "test.h"
int test(void)
{
   int x = add(10,15);
   return x;
}

EDIT: See here for better explanation of C99 inline usage: How to declare an inline function in C99 multi-file project?

However, this can cause all sorts of weird behavior with the resulting object code. For example, I've seen a compiler from a major MCU mfg (who will intentionally go unnamed) generate object code for inline functions #included in a given translation unit instead of inlining them. The file was included in several places and contained many functions so this caused a massive increase in overall ROM usage throughout the code base because the linker was also incapable of removing dead code (see --gc-sections for gcc) AND failed to improve performance because the functions were never actually inlined, even though it was technically the correct use of inline.

Our solution to this particular problem was to convert all the functions to macros (which gave the perfomance benefit intended with inline) but an alternate approach would have been removing the inline from the declaration and moving the definiton to a single .c file.

TL;DR: If using inline for MCUs, 1) consult your compiler manual, and 2) keep an eye on object code generated.

Community
  • 1
  • 1
Brian McFarland
  • 9,052
  • 6
  • 38
  • 56
  • @user1806687 I stand corrected (slightly) on the C99 `inline` usage. See updated answer & link for more info. Cautions about watching the generated code still stands though. – Brian McFarland Feb 19 '15 at 13:33
  • `static inline` should make sure that no symbol and code is generated for a function. – nwellnhof Feb 19 '15 at 13:36
  • @nwellnhof - it didn't for the compiler in question. But for GCC, he should be fine. – Brian McFarland Feb 19 '15 at 13:37
  • @BrianMcFarland So how would I use `static inline` in code to achieve this? – user1806687 Feb 19 '15 at 13:47
  • See updated example. I believe it will do what you're after if I understand the question correctly. – Brian McFarland Feb 19 '15 at 13:49
  • @BrianMcFarland I mean how would I use this. Should I use `staic inline void some_func(void);` in test.h, and `static inline void some_func(void) {}` in main.c. But this gives errors. – user1806687 Feb 19 '15 at 13:53
  • No, remove the `static inline void some_funct(void){}` from main.c. Inline functions technically cannot exist across multiple translation units. Putting it in the header is effectively doing a copy/paste into every `.c` that includes the header, but you still only *maintain* one version of the code. – Brian McFarland Feb 19 '15 at 13:56
  • @BrianMcFarland Ahh, it makes sense now. Thanks! – user1806687 Feb 19 '15 at 14:02
2

Assuming you mean what you say, that the function in question is a callback, you can't inline a callback. It doesn't make sense, the callback-call usually happens through a function pointer, I don't think you can expect the compiler to prove that its value is constant (and known at compile-time) so that it can replace the call with inlined code.

unwind
  • 391,730
  • 64
  • 469
  • 606
1

You can use inline keyword in C but if you're using GNU GCC compiler it will require inline functions to be static functions also. So you will be only available to use these functions on the same source file. If you want to declare a global inline function that you define in some header file and use it on source files that includes that header file you can use GNU GCC's always_inline attribute as following:

static inline __attribute__((always_inline)) int foo(int a)
{
  return a+2;
}

Don't forget to declare body of the inline function in the same header file.

Muhammed Kadir
  • 576
  • 1
  • 5
  • 17
-1

The way it works is exactly like that, you will have only one definition of the function, say it's the function int add(int x, int y); then you define it in main.c

main.c:

int add(int x, int y)
{
    return x + y;
}

then if you want to use it in another c file all you need is this

test.c

int add(int x, int y); /* just a declaration, a function prototype */

int addWrapper(int x, int y)
{
    return add(x, y);
}

compile it like this

gcc -Wall -Werror main.c test.c -o some_output_file_name

and the linker will take care of finding the function definition.

If the function is not defined in any of the compiled files, then a

Undefined reference to `int add(int x, int y);' in ...

error will be issued.

If you want to force the compiler to insert the function body, then insert the function body yourself, use a preprocessor macro

header.h

#define add(x,y) ((x) + (y))

and then

#include "header.h"

int addWrapper(int x, int y)
{
    return add(x, y);
}

will replace add(x, y) with x + y.

If the function returns void then a nice trick is to use this

#define inlinedFunction(parameters) \
    do {                            \
        /* function body here */    \
    } while (0)

you should add a continuation backslash at the end of every line in the macro definition.

Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
  • But that doesn't *inline* the function as the OP is requesting, does it? That's just a standard function call. – lurker Feb 19 '15 at 13:00
  • Using macros could work, but is just ugly. You're sure there isnt another way? I really need the user (main.c) to define that function, not somehere in a header. – user1806687 Feb 19 '15 at 13:19
  • @user1806687 If you want to ensure that the code will be replaced there isn't and why is it ugly? you will have it in your header file and call it as if it was a function. – Iharob Al Asimi Feb 19 '15 at 13:24
  • Because the user will have to make a `#define` statement instead of just making a function. – user1806687 Feb 19 '15 at 13:50
  • @user1806687 I don't understand, why would the user need a define? you provide it within your header file. – Iharob Al Asimi Feb 19 '15 at 13:57
  • 1
    Inline functions and macros are completely different things. You define inline functions with "inline" keyword. Inline functions are parsed by compiler but macros are parsed by preprocessor and inline functions are typesafe but not macros. So this doesn't answer the question. – Muhammed Kadir Mar 25 '19 at 13:37