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
Related
What I currently have
#define _CMPLT8 _mm_cmplt_epi8 // int8_t
#define _CMPLT32 _mm_cmplt_epi32 // int32_t
What I want (something similar to the following code)
#define _CMPLT(T) ( \
if(sizeof(T)==1) return _mm_cmplt_epi8 \
else if(sizeof(T)==4) return _mm_cmplt_epi32 \
else #error \
)
How could I this code?
If you want to return a string based on a type I'd go for generics:
#define _CMPLT(T) \
_Generic( (T), \
char: "1", \
int: "4", \
default: "0")
int main(void) {
char a;
int b;
printf("%s%s\n", _CMPLT(a), _CMPLT(b));
}
But I feel you want to call functions depending on arg type, so in that case:
#define _CMPLT(X, Y) _Generic((X), \
int8_t: _mm_cmplt_epi8(X, Y), \
int32_t: _mm_cmplt_epi32(X, Y) \
)
int main(void) {
int8_t a = 0, b = 1;
int32_t c = 2, d = 3;
printf("%d%d\n", _CMPLT(a, b), _CMPLT(c, d));
}
If you really need to use strings and sizeof, and can use compound statements, would this work for you?
#include <stdio.h>
#define _CMPLT(T) ({ \
switch(sizeof(T)) { \
case 1: "1"; \
case 4: "4"; \
}; \
"0"; \
})
int main(void) {
printf("%s%s\n",
_CMPLT(char), _CMPLT(int));
}
I want to express logic like this in a statement expression
if (!pass_check) {
return 1;
}
if (!pass_check2) {
return 2;
}
return 0;
My macro does some checking before doing its actual thing. For reasons, I can't use a function here; it must be a macro
#define FOO ({ \
if (!pass_check) { \
return 1; \
} \
if (!pass_check2) { \
return 2; \
} \
return 0; \
})
However, I can't seem to use return in macros, only the value of the last subexpression is returned as stated in the documentation. How can I make this have the intended effect?
Edit: added minimal working example. This macro will not compile,
but this is how I intend to use it. The idea is that I want to run some checks before foo() runs, and I want to accomplish this by wrapping foo() in a macro:
int pass_check1(int i) {
if (i > 10) return 1;
return 0;
}
int pass_check2(int i) {
if (i < 0) return 1;
return 0;
}
int foo(int i) {
// foo must be called only after the previous checks pass
// the checks above are examples only, the idea is that I should
// be able to prepend any number pass_checkN checks before foo()
// is called
return 0;
}
// FOO should return 1 if either check fails, else whatever foo() returns.
#define FOO(i) ( \
if (!pass_check(i)) { \
return 1; \
} \
if (!pass_check2(i)) { \
return 2; \
} \
foo(i); \
})
int main() {
int ret = FOO(i);
}
I think you just need your macro to use nested ternaries, as follows:
#define FOO (!pass_check ? 1 : (!pass_check2 ? 2 : 0))
As you noted, the "return" value of a macro is just the value of the last expression, and this will do what you want.
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)
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)
I am trying to define a macro -
#define macro1(arg1) \
do{ \
int _state = 0; \
if (arg1 && arg1->member_) \
_state = arg1->member_->state_; \
printf("%d", _state); \
} while(0)
A *a = new A():
macro1(a); // Works
macro1(NULL); // Error
The specific error I see is -
"error: base operand of ‘->’ is not a pointer"
Aren't we allowed to pass NULL as an argument to macros?
Macro expansion is just text replacement, so when you passed NULL, it will expand to NULL->member, clearly it is an error. One way is to use a temporary variable for that:
#define macro1(arg1) \
do{ \
A* p = (arg1);
int _state = 0; \
if (p && p->member_) \
_state = p->member_->state_; \
printf("%d", _state); \
} while(0)
A *a = new A():
macro1(a);
macro1(NULL);
This way both cases will work.
You have to understand what's a macro in order to understand your mistake. Except for the compiler, there's an animal called pre-compiler. It replaces all the macros' references by the actual code defined for this macro. So this code:
#define macro1(arg1) \
do{ \
int _state = 0; \
if (arg1 && arg1->member_) \
_state = arg1->member_->state_; \
printf("%d", _state); \
} while(0)
A *a = new A():
macro1(a); // Works
macro1(NULL); // Error
will be replaced with:
A *a = new A():
do{
int _state = 0;
if (a && a->member_)
_state = a->member_->state_;
printf("%d", _state);
} while(0)
do{
int _state = 0;
if (NULL && NULL->member_)
_state = NULL->member_->state_;
printf("%d", _state);
} while(0)
THIS code will be compiled. And now you can see for yourself what's the root cause of the compilation error.
Macros are just a text replacement.
for example, if you have
#define mac(x) x/x
that would work for must numbers but not for 0, because it will be replaced with 0/0 which is not defined.
in your case if you pass NULL it will be replaced with:
do{ \
int _state = 0; \
if (NULL && NULL->member_) \
_state = NULL ->member_->state_; \
printf("%d", _state); \
} while(0)
so what is the meaning of NULL->member_ in this case. No sense, hence it fails.
consider using a regular function, or two macros one for regular pointers and one for NULL pointers, and make your code as this:
if (ptr)
macro1(ptr);
else
macro2;
Small adjust let the pre-compiler know the type size + a forward declaration and it'll work:
#define macro1(arg1) \
do{ \
int _state = 0; \
if ((arg1) && ((A*)arg1)->member_) \
_state = ((A*)arg1)->member_->state_; \
printf("%d", _state); \
} while(0)
Complete code:
#include <stdio.h>
class A;
#define macro1(arg1) \
do{ \
int _state = 0; \
if ((arg1) && ((A*)arg1)->member_) \
_state = ((A*)arg1)->member_->state_; \
printf("%d", _state); \
} while(0)
struct member{
int state_;
};
class A {
public:
member* member_;
};
int main(int n, char** arg) {
A* a = new A();
a->member_ = new member();
a->member_->state_ = 1;
macro1(a);
macro1(NULL);
return 0;
}
The more fundamental problem is that NULL is not a pointer, it is a macro for 0.
Hence when you pass in NULL, it is equivalent to passing in 0, which of course is an error.
As other answers have mentioned, giving the argument an explicit cast will fix it
(A*)arg1
As a side note, you should be using nullptr in C++ for a null pointer.
EDIT: As #AjayBrahmakshatriya pointed out, NULL can be defined as (void*)0 (in C only) which will be a pointer, but the argument still holds true, NULL is not a pointer of your type.
EDIT2: Apparently in C++11 and later, NULL can be defined as nullptr