Генерация нескольких похожих функций с препроцессором C - PullRequest
2 голосов
/ 29 мая 2019

Я хочу сгенерировать несколько похожих функций, заменяя только одно слово в функции.

В качестве примера для каждого из нижеприведенного:

OBJECT = customer
OBJECT = account

используйте шаблон функции:

void add_OBJECT_to_array(void* item_ptr, int pos)
{
    mtx_lock(&OBJECT_array_mtx);
    OBJECT_array[pos] = *(OBJECT_t*)item_ptr;
    mtx_unlock(&OBJECT_array_mtx);
    return;
}

Чтобы я мог позвонить

add_order_to_array(ord, 1);
add_customer_to_array(cust, 1);

Возможно ли это?

Ответы [ 2 ]

5 голосов
/ 29 мая 2019

Вполне возможно. Вам просто нужно знать об операторе конкатенации препроцессора ##. Следующий код сгенерирует две функции add_order_to_array и add_customer_to_array.

#define GENERATE_FUNC(OBJECT) \
    void add_ ## OBJECT ## _to_array(void* item_ptr, int pos)\
    {                                                        \
        mtx_lock(&OBJECT ## _array_mtx);                     \
        OBJECT ## _array[pos] = *(OBJECT ## _t*)item_ptr;    \
        mtx_unlock(&OBJECT ## _array_mtx);                   \
        return;                                              \
    }                                                      

GENERATE_FUNC(order)
GENERATE_FUNC(customer)

Вывод препроцессора будет (к сожалению, он не учитывает форматирование):

void add_order_to_array(void* item_ptr, int pos) { mtx_lock(&order_array_mtx); order_array[pos] = *(order_t*)item_ptr; mtx_unlock(&order_array_mtx); return; }
void add_customer_to_array(void* item_ptr, int pos) { mtx_lock(&customer_array_mtx); customer_array[pos] = *(customer_t*)item_ptr; mtx_unlock(&customer_array_mtx); return; }
2 голосов
/ 29 мая 2019

Да, это возможно:

#define DECLARE_ADD_FUNCTION(__obj)                         \
    void add_##__obj##_to_array(void* item_ptr, int pos)    \
    {                                                       \
        mtx_lock(&__obj##_array_mtx);                       \
        __obj##_array[pos] = *(__obj##_t*)item_ptr;         \
        mtx_unlock(&__obj##_array_mtx);                     \
        return;                                             \
    }

DECLARE_ADD_FUNCTION(customer)
DECLARE_ADD_FUNCTION(account)

Когда вы смотрите на вывод препроцессора, вы получаете:

gcc -E foo.c

void add_customer_to_array(void* item_ptr, int pos) { mtx_lock(&customer_array_mtx); customer_array[pos] = *(customer_t*)item_ptr; mtx_unlock(&customer_array_mtx); return; }
void add_account_to_array(void* item_ptr, int pos) { mtx_lock(&account_array_mtx); account_array[pos] = *(account_t*)item_ptr; mtx_unlock(&account_array_mtx); return; }

Выможно даже убедиться, что тип указателя является правильным, изменив прототип функции на add_##__obj##_to_array(__obj##_t *, int pos)

...