I want to generate multiple similar functions replacing just one word across the function.
As an example, for each of the below:
OBJECT = customer
OBJECT = account
use the function template:
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;
}
So that I can call
add_order_to_array(ord, 1);
add_customer_to_array(cust, 1);
Is this possible?
Totally possible. You just need to know about the preprocessor concatenation operator ##. The following code will generate two functions add_order_to_array and 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)
The preprocessor output will be (unfortunately it does not respect formatting):
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; }
Yes it's possible:
#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)
When you look at the output of the preprocessor you get:
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; }
You can even ensure that the pointer type is the correct type by changing the function prototype to add_##__obj##_to_array(__obj##_t *, int pos)
Related
I am trying to automatise the generation of struct in my code for which the syntax is specify by the Midas Library. The difficulty here lies in the parallel building of const char* dictionary that mimic the struct definition:
typedef struct {
BOOL runColdStartScript;
BOOL runPedestalScript;
BOOL triggerCommunicationTest;
BOOL updateOdbParameters;
BOOL runCmdBuffer;
BOOL runSelectedScript;
} myHotLink;
myHotLink hotLinkContainer{};
const char *hot_links_str[9] = { \
"[.]", \
"runColdStartScript = BOOL : n", \
"runPedestalScript = BOOL : n", \
"triggerCommunicationTest = BOOL : n", \
"updateOdbParameters = BOOL : n", \
"runCmdBuffer = BOOL : n", \
"runSelectedScript = BOOL : n", \
"", nullptr
};
Ideally I'd like to generate this piece of code with a macro. For example:
MAKE_HOT_LINK(
myHotLink,
{ BOOL, runColdStartScript, n },
{ BOOL, runPedestalScript, n },
...
)
Does someone have an idea on how to define (and properly call) the MAKE_HOT_LINK macro?
Cheers!
You could use some metamacros to define the fields you want and some other macros that expand those to the declaration and descriptor:
#define MYHOTLINK_FIELDS(M) \
M(BOOL, runColdStartScript, n) \
M(BOOL, runPedestalScript, n) \
M(BOOL, triggerCommunicationTest, n) \
M(BOOL, updateOdbParameters, n) \
M(BOOL, runCmdBuffer, n) \
M(BOOL, runSelectedScript, n) \
#define FIELD_DECL(TYPE, NAME, TAG) TYPE NAME;
#define FIELD_DESCRIPTOR(TYPE, NAME, TAG) #NAME " = " #TYPE " : " #TAG,
#define DECLARE_STRUCT(STYPE) struct { STYPE(FIELD_DECL) }
#define STRUCT_DESCRIPTOR(STYPE) { "[.]", STYPE(FIELD_DESCRIPTOR) "", nullptr }
typedef DECLARE_STRUCT(MYHOTLINK_FIELDS) myHotLink;
myHotLink hotLinkContainer {};
const char *hot_links_str[] = STRUCT_DESCRIPTOR(MYHOTLINK_FIELDS);
would expand to (equivalent of) what you have above.
Let's say I have Stack that I want to use to store various different types. If I define the interface as follows:
// stack.h
typedef struct Stack {
size
push // function pointers
pop
etc.
};
And let's say I want to support two different stack types, and so I create:
// stack.c
Stack person_stack;
person_stack->push = push_to_person_stack;
Stack animal_stack;
animal_stack->push = push_to_animal_stack;
How can I make it such that the push_to_<type>_stack is effectively private and the caller of that stack is only able to see the Stack->push function? Or maybe that's not possible in C and you need an OO language to do it, but what would be an example of having a unified interface for this?
You can use function pointers to emulate methods in other OOP languages but still you need to pass the instance to the method otherwise there is no way to know on which stack to push. Also using void* would make more problems than it solves.
struct Stack {
void (*push)(Stack* self, void* data); //< self here
}
Here is a way that I use to emulate template/generics in c by using macros (reference : https://github.com/wren-lang/wren/blob/main/src/vm/wren_utils.h#L16)
#define DECLARE_STACK(type) \
typedef struct { \
type* data; \
int size; \
int capacity; \
} type##Stack; \
void type##Stack_push(type##Stack* self, type value); \
type type##Stack_pop(type##Stack* self); \
void type##Stack_init(type##Stack* self); \
#define DEFINE_STACK(type) \
void type##Stack_push(type##Stack* self, type value) { \
if (self->capacity <= self->size + 1) { \
self->capacity = self->capacity * 2; \
self->data = realloc(self->data, sizeof(type) * self->capacity); \
} \
self->data[self->size] = value; \
self->size++; \
} \
\
type type##Stack_pop(type##Stack* self) { \
self->size--; \
return self->data[self->size]; \
} \
\
void type##Stack_init(type##Stack* self) { \
self->size = 0; \
self->capacity = 2; \
self->data = malloc(sizeof(type) * self->capacity); \
} \
typedef struct Person {
int id;
} Person;
DECLARE_STACK(Person); // in person.h
DEFINE_STACK(Person); // in person.c
int main() {
Person p1, p2, p3, p4;
p1.id = 1; p2.id = 2; p3.id = 3; p4.id = 4;
PersonStack stack;
PersonStack_init(&stack);
PersonStack_push(&stack, p1);
PersonStack_push(&stack, p2);
PersonStack_push(&stack, p3);
Person p;
p = PersonStack_pop(&stack); // p.id = 3
p = PersonStack_pop(&stack); // p.id = 2
PersonStack_push(&stack, p4);
p = PersonStack_pop(&stack); // p.id = 4
p = PersonStack_pop(&stack); // p.id = 1
return 0;
}
And If you want to debug, macros are harder to debug the flow with a debugger, so I've used a python script to generate the expansion of the macro to source and header files before compile (I build with scons which is python based so I automated the source files generation)
Im trying to create a preprocessor macro to allocate and free memory for matrix/vector of any data type. Here is what I have so far:
#ifndef H_ARRAY_H
#define H_ARRAY_H
#include "xmalloc.h"
#define make_vector(v,n) (v = xmalloc( (n) * sizeof *(v))
#define free_vector(v) do { free(v) ; v = NULL; } while(0)
#define make_matrx(a , m , n) do { \
size_t make_matrix_loop_counter; \
make_vector(a, (m) + 1); \
for ( make_matrix_loop_counter = 0; make_matrix_loop_counter < (m) ; make_matrix_loop_counter++) \
make_vector((a)[make_matrix_loop_counter], (n)); \
(a)[m] = NULL; \
} while (0)
#define free_matrix(a) do { \
if (a != NULL){ \
size_t make_matrix_loop_counter; \
for (make_matrix_loop_counter = 0 ; (a) [make_matrix_loop_counter] != NULL; make_matrix_loop_counter++) \
free_vector((a)[make_matrix_loop_counter]); \
free_vector(a); \
a != NULL; \
} \
} while (0)
But when I try to construct a matrix it spits out an error "implicit declaration of function ‘make_matrix’".
Any suggestions.
PS: xmalloc.h allocate space
Are you sure your MACRO name should read make_matrx instead of make_matrix?
You need to correct the macro name spelling. Otherwise, when you use make_matrix() in your code, it does not find a corresponding function.
I want to create a function wrapper, with a defined body, that calls the wrapped function.
How can I get from this:
int foo (int arg)
{
do_something(arg);
}
To something equivalent to this:
int foo (int arg)
{
always_do_this();
real_foo(arg);
}
int real_foo (int arg)
{
do_something(arg);
}
I must do the transformation automatically and it has to be signature independent and in compile time.
How can I do it?
You can do this with macros, here's a quick example:
#define CREATE_FUNC_WRAPPER(NAME, ARG) \
int NAME(ARG arg) { \
real_##NAME(arg); \
}
int real_foo(int a) {
printf("real_foo speaking: %d\n", a);
}
CREATE_FUNC_WRAPPER(foo, int)
int main() {
foo(1);
}
You need to modify it to fit your needs, your question is unclear.
I had to give up from installing wrapper on function declaration, the solution was to install the wrappers on function call using compound statements. Bellow the two macros I created to do that, one deals with calls returning void, other with any call that returns a value:
#define PROFILE_VOID(call) \
({ \
hal_time_t stop, start; \
hal_getTime(&start); \
call; \
hal_getTime(&stop); \
__PROFILE_PRINT(call, hal_secondsElapsed_d(&stop, &start)); \
})
#define PROFILE(call) \
({ \
typeof(call) __ret; \
hal_time_t stop, start; \
__profile_nested_cnt++; \
hal_getTime(&start); \
__ret = call; \
hal_getTime(&stop); \
__profile_nested_cnt--; \
__PROFILE_PRINT(call, hal_secondsElapsed_d(&stop, &start)); \
__ret; \
})
Example of use:
PROFILE_VOID(func_returning_void(arg, arg2)); //Void func
PROFILE(other_funcs()); // Any non void func
PROFILE(x = func(x, y, z)); //Any statement
x = PROFILE(func(x, y, z)); //Same as previous
if (PROFILE(func()) == 0) { } //Inside conditionals
if (PROFILE(func() == 0)) { } //Same as previous
I would like to run the function pointed by my struct with auto-filling functionality.
This is the part that I'm working on:
#include <stdio.h>
#include <stdlib.h>
struct Fra { //Fraction
int n; //Numerator
int d; //Denominator
void (*p)(struct Fra*);
void (*sD)(int, struct Fra*);
void (*sN)(int, struct Fra*);
};
void print(struct Fra*);
void setDenom(int, struct Fra*);
void setNum(int, struct Fra*);
int main() {
struct Fra* fraA = 0;
fraA = (struct Fra*) malloc(sizeof(struct Fra));
fraA->sN = setNum;
fraA->sN(2, fraA);
fraA->sD = setDenom;
fraA->sD(3, fraA);
fraA->p = print;
fraA->p(fraA);
return 0;
}
And this is what I've been trying to achieve
From:
fraA->sN(2, fraA);
fraA->sD(3, fraA);
fraA->p(fraA);
To:
fraA->sN(2);
fraA->sD(3);
fraA->p();
After spending some time on trial-error, I've arrived to the conclusion that I need assistance on this. I've tried browsing, but it seems I don't have the right keyword, so I'm unable to verify whether this question is a double or not.
Thanks for any help.
You could declare some macros to savely always pass the correct reference, that's all you can do:
#define FRA_NEW(this, sN sD, sP) \
{ \
(this) = calloc(sizeof(*(this))) \
if (this) \
{ \
(this)->sN = (sN); \
(this)->sN = (sD); \
(this)->sN = (sP); \
} \
}
#define FR_DELETE(this) \
free(this)
#define FRA_PRINT(this) \
(this)->print(this)
#define FRA_SETNUM(this, num) \
(this)->setNum(this, num)
#define FRA_SETDENOM(this, denom) \
(this)->setDenom(this, denom)
Also I'd propose to have "this" always as first parameter to the "member"-functions.
int main(void)
{
struct Fra * fraA = NULL;
FRA_NEW(fraA, setNum, setDenom, print);
if (NULL == fraA)
{
perror("FRA_NEW() failed");
return 1;
}
FRA_SETNUM(fraA, 2);
FRA_SETDENOM(fraA, 3);
FRA_PRINT(fraA);
FRA_DELETE(fraA);
return 0;
}
The only really useful way I can think of would be to provide functions which do the job:
void call_print(struct Fra* fra)
{
fra->p(fra);
}
void call_setDenom(int val, struct Fra* fra)
{
fra->sD(val, fra);
}
void call_setNum(int val, struct Fra* fra);
{
fra->sN(val, fra);
}
and use these:
call_setNum(2, fraA);
call_setDenom(3, fraA);
call_print(fraA);