Append items to an array with a macro, in C

后端 未结 4 1630
广开言路
广开言路 2021-01-18 00:24

I have an array (C language) that should be initialized at compile time.

For example:

DECLARE_CMD(f1, arg);
DECLARE_CMD(f2, arg);
         


        
4条回答
  •  猫巷女王i
    2021-01-18 01:17

    Yes, you can build dynamic arrays at compile time (not at runtime) (and thank's to Mitchel Humpherys), the idea is to declare your callbacks in the same section like this:

    EXAMPLE:

    Suppose you have three files a.c, b.c main.c and i.h

    into i.h

    typedef void (*my_func_cb)(void);
    
    typedef struct func_ptr_s {
           my_func_cb cb; /* function callback */
    } func_ptr_t;
    
    #define ADD_FUNC(func_cb)                        \
        static func_ptr_t ptr_##func_cb              \
        __attribute((used, section("my_array"))) = { \
            .cb = func_cb,                           \
        }
    

    into a.c

    #include "i.h"
    
    static void f1(void) {
       ....
    }
    
    ADD_FUNC(f1);
    

    into b.c

    #include "i.h"
    
    static void f2(void) {
       ....
    }
    
    ADD_FUNC(f2);
    

    into main.c

     #include "i.h"
     
     static void f3(void) {
       ....
     }
    
     ADD_FUNC(f3);   
    
     #define section_foreach_entry(section_name, type_t, elem)    \
         for (type_t *elem =                                      \
                ({                                                \
                    extern type_t __start_##section_name;         \
                    &__start_##section_name;                      \
                });                                               \
                elem !=                                           \
                ({                                                \
                    extern type_t __stop_##section_name;          \
                    &__stop_##section_name;                       \
                });                                               \
                ++elem)
                
    
     int main(int argc, char *argv[])
     {
        section_foreach_entry(my_array, func_ptr_t, entry) {
                entry->cb(); /* this will call f1, f2 and f3 */
        }
    
        return 0;
     }
    

    IMPORTANT

    sometimes the compiler optimizes start/end sections variables, it wipes them out, so when you try to use them, you will have a linker error: error LNK2019: unresolved external symbol ...

    to fix this problem, i use the following:

    1. Try to print your linker script:

      gcc -Wl,-verbose

    copy the text between the two:

    ==================================================

    in a file (example lnk.lds), you should see thing like:

    /* Script for -z combreloc: combine and sort reloc sections */

    OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64","elf64-x86-64")

    ........

    1. ADD your section to the linker script file lnk.lds after the section .data like this (my defined section is called my_array as in the example):
      __start_my_array = .;
      .my_array :
      {
        *(.my_array)      
      }
      __stop_my_array = .;
    
    1. Compile your program with the updated linker script like this:

      gcc -O3 -Xlinker -T"lnk.lds" file.c -o program

    2. If you type strings program | grep "__start_my_array" you should find it.

提交回复
热议问题