I am browsing through telegram-cli source code to make some changes. However, I am stuck at a syntax that I am not able to understand.
#define user_cmp(a,b) (tgl_get_peer_id ((a)->id) - tgl_get_peer_id ((b)->id))
DEFINE_TREE(user, struct tgl_user *,user_cmp,0)
static void notify_status (struct tgl_user *U, void *ex) {
struct tgl_state *TLS = ex;
if (TLS->callback.user_status_update) {
TLS->callback.user_status_update (TLS, U);
}
}
static void status_notify (struct tgl_state *TLS, void *arg) {
tree_act_ex_user (TLS->online_updates, notify_status, TLS);
tree_clear_user (TLS->online_updates);
TLS->online_updates = NULL;
TLS->timer_methods->free (TLS->online_updates_timer);
TLS->online_updates_timer = NULL;
}
The tree_act_ex_user function is not defined anywhere and IDE is navigating to second line i.e. DEFINE_TREE(user, struct tgl_user *,user_cmp,0). Please explain or point to a reference what construct is this?
what construct is this?
A macro expansion that defines a function. A reduced example:
#define DEFINE_TREE(NAME, some_arg, some_arg2, yet_another_arg) \
static void tree_act_ex_##NAME() { \
do_something(); \
}
DEFINE_TREE(some_string, arg1, arg2, arg3)
// expands to:
// static void tree_act_ex_some_string() { do_something(); }
int main() {
tree_act_ex_some_string();
}
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
Question:
I want to create a reusable function, because in my code much line that use same code structure
The code using for example if { if { `Only here's the different` } }. Of course the pattern not same as this, this using as an example.
I've been code using framework such as Laravel, there's a directive called as SLOT
Is there any way I can inject code in the middle of for loop? Or anything same as SLOT inside C programming
Sample code:
void functionname() {
for (int i=0; i < total_count; i++) {
SELECT THE ITEM (i)
if (a == b) return;
if (c) {
CODE INJECT HERE
}
}
}
Forget to mention before, a, b, c and so on from the coding above is getting from ITEM (i)
You should use a callback. i.e. you should send a function pointer (i.e. the address of the function you want to execute) and use that pointer to execute that function inside your loop.
In the example below, p is a pointer to a function taking a const char * for a parameter and returning an int.
int (*p)(const char *s) ;
NB: all functions passed as parameter, to be used as callback must have the same prototype (which is why such functions are often declared taking a generic pointer parameter void * to accept whatever you've got to send to the function).
So with your example and with functions taking void * as a parameter and returning void *, and with param defining a parameter that you want to feed to your function, this gives us the following code:
void functionname(void *(*func)(void *)) {
for (int i=0; i < total_count; i++) {
SELECT THE ITEM (i)
if (a == b) return;
if (c) {
func(¶m);
}
}
}
you can call your function wiht whatever function respecting the prototype... For instance:
void *my_custom_function(void *param) {
...
}
...
functionname(my_custom_function);
...
As suggested in the comment by KamilCik, use function pointers:
void functionname(void *fx)(void)) {
for (int i=0; i < total_count; i++) {
SELECT THE ITEM (i)
if (a == b) return;
if (c) {
//CODE INJECT HERE
fx();
}
}
}
And use it like
void foo(void) { puts("foo() called"); }
void bar(void) { puts("bar() called"); }
int main(void) {
functionname(foo);
functionname(bar);
}
For a concrete example:
#include <stdio.h>
int a = 1;
int b = 2;
typedef void (*selector)(int, int *);
typedef void (*injector)(void);
void select1(int x, int *c) { printf("%s: %d\n", __func__, *c = x); }
void select2(int x, int *c) { printf("%s: %d\n", __func__, *c = x); }
void inject1(void) { printf("%s\n", __func__); }
void inject2(void) { printf("%s\n", __func__); }
void
functionname(size_t total_count, selector SELECT_THE_ITEM,
injector CODE_INJECT_HERE )
{
for (size_t i=0; i < total_count; i++) {
int c;
SELECT_THE_ITEM (i, &c);
if (a == b) return;
if (c) {
CODE_INJECT_HERE();
}
}
}
int
main(void)
{
functionname(2, select1, inject1);
functionname(3, select2, inject2);
}
You can do what you ask by defining your "CODE INJECT HERE" as the body of a function, and passing a pointer to that function:
void functionname(void (*inject)(void)) {
for (int i=0; i < total_count; i++) {
SELECT THE ITEM (i)
if (a == b) return;
if (c) {
inject();
}
}
}
void do_something(void) {
CODE INJECT HERE
}
void do_something_else(void) {
OTHER CODE INJECT HERE
}
int main(void) {
functionname(do_something));
functionname(do_something_else));
}
Do note, however, that this is not simple code injection in the same sense as a macro would provide. In particular, the executions of do_something() and do_something_else() will not see the local variables of main() or of functionname(), and the do_* functions can return only from themselves, not from a caller further up the chain. The former can be mitigated to some extent by passing parameters to the do_* functions (which they must be prepared to accept).
Another alternative would be to use a macro instead of a function to provide the common framework. It would look something like this:
#define frame_it(x) do { \
for (int i=0; i < total_count; i++) { \
SELECT THE ITEM (i) \
if (a == b) return; \
if (c) { \
x \
} \
} \
} while (0)
int main(void) {
frame_it(
CODE INJECT HERE
);
frame_it(
OTHER CODE INJECT HERE
);
}
That keeps the CODE INJECT HERE code in the function using it, which might be advantageous if in fact each such piece of code is used in only one place. It also allows both that code and the framing code to access the local variables of the function in which they appear, and to return from that function if desired.
However, macro programming has earned a mostly-deserved reputation for being error prone and difficult to read and debug. Your particular need may be one that is well served by this approach, but do not choose this direction lightly.
Function pointers are great for this. You can typedef the function signatures you'd like to support. Example:
/* A signature for condition checking functions, taking a "void*" argument
and returning true or false */
typedef bool(*cond_check_t)(void*);
/* A signature for functions to execute if a condition is met. This takes a
"void*" argument but you decide what you need */
typedef void(*exec_t)(void*);
You can package these two in a struct to form a nice pair:
typedef struct {
cond_check_t checker;
exec_t executor;
} check_exec_t;
And with that, another struct to keep a bunch of these condition and executor pairs:
typedef struct {
size_t size;
size_t capacity;
check_exec_t *conditionals;
} cond_pack_t;
You then create support functions for adding checkers and executors and a function to processes one of these packaged checkers and executors.
cond_pack_t* cond_pack_create(size_t capacity) {
cond_pack_t* cp = malloc(sizeof(*cp));
if(cp) {
cp->conditionals = malloc(sizeof(*cp->conditionals) * capacity);
if(cp->conditionals) {
cp->size = 0;
cp->capacity = capacity;
} else {
free(cp);
cp = NULL;
}
}
return cp;
}
void cond_pack_destroy(cond_pack_t *cp) {
free(cp->conditionals);
free(cp);
}
bool cond_pack_add(cond_pack_t *cp, cond_check_t checker, exec_t executor) {
if(cp->size == cp->capacity) return false;
cp->conditionals[cp->size].checker = checker;
cp->conditionals[cp->size].executor = executor;
++cp->size;
return true;
}
void cond_pack_process(cond_pack_t *cp) {
for(size_t i = 0; i < cp->size; ++i) {
if(cp->conditionals[i].checker(NULL)) { /* execute checker */
cp->conditionals[i].executor(NULL); /* execute executor */
}
}
}
With that, a usage example could look like this
//---
bool some_check(void *foo) {
return true;
}
void some_executor(void *foo) {
printf("some_executor\n");
}
bool some_other_check(void *foo) {
return false;
}
void some_other_executor(void *foo) {
printf("some_other_executor\n");
}
int main() {
cond_pack_t *cp = cond_pack_create(10);
if(cp) {
cond_pack_add(cp, some_check, some_executor);
cond_pack_add(cp, some_other_check, some_other_executor);
cond_pack_process(cp); /* run all the checkers / executors */
cond_pack_destroy(cp);
}
}
Demo
I am looking for a fancy way to link function pointers and enums.
In my case I have a message queue that holds a event id and some data associated with the event.
some simple pseudo code:
event=(eid, data)
switch(eid) {
case eid1:
handler1(data);
break;
case edi2:
handler2(data);
break;
}
Now I like to do some optimization. If the event id has the value of the function called inside of the switch case statement I can save the switch case decode by preserving a nice readability of the code.
event=(eid, data)
eid(data)
Now if I am putting it into an example like:
static void abc(void * p) {
}
static void abc2(void * p) {
}
enum eventId {
eid1 = abc,
eid2 = abc2
} xyz;
My compiler tells:
error: enumerator value for 'eid1' is not an integer constant eid1 = abc
What is absolutely right.
Any ideas how to solve that problem?
Use an array of function pointers, and use the enum as the index.
typedef void (*handler_func)(void *);
handler_func event_handlers[] = { abc, abc2 };
enum eventId {
eid1 = 0,
eid2 = 1,
eid_max
}
if (eid < eid_max) event_handlers[eid](data);
enums cannot be linked with other data in C, but the preprocessor can generate code for you in the form of X-Macros.
#include <stdio.h>
typedef void (*handler_func)(void *);
static void handler1(void *const param) {
printf("Event 1: %p.\n", param);
}
static void handler2(void *const param) {
printf("Event 2: %p.\n", param);
}
#define EVENT(X) \
X(EID1, &handler1), \
X(EID2, &handler2)
#define PARAMA(A, B) A
#define PARAMB(A, B) B
#define STRINGISEA(A, B) #A
enum Event { EVENT(PARAMA) };
static const handler_func event_handlers[] = { EVENT(PARAMB) };
static const char *const event_strings[] = { EVENT(STRINGISEA) };
/* Everything will be the same size, pick one. */
static const size_t event_size = sizeof event_strings / sizeof *event_strings;
int main(void) {
size_t i;
void *const param = (void *)0x100;
for(i = 0; i < event_size; i++) {
printf("Calling %s.\n", event_strings[i]);
event_handlers[i](param);
}
return 0;
}
Gives,
Calling EID1.
Event 1: 0x100.
Calling EID2.
Event 2: 0x100.
The advantage of this implementation is it's a single source of truth; if one decided to add more events, they will only need to be added in one spot. The disadvantage is it's hard to read.
As an extension to the answer of #Barmar, you can use a technique called X macro, to keep corresponding (eid, handler) pairs in order. Note that you need only to change the definition of LIST_OF_EVENTS macro, adding or deleting pairs as needed.
void handler1(void*);
void handler2(void*);
void handler3(void*);
#define LIST_OF_EVENTS X(eid1, handler1), X(eid2, handler2), X(eid3, handler3)
#define X(id, x) id
enum evID { LIST_OF_EVENTS };
#undef X
#define X(x, handler) handler
void (*handlers[])(void*) = { LIST_OF_EVENTS };
#undef X
int get_event(void**);
void event_loop(void)
{
for (;;) {
void *data;
int eid = get_event(&data);
handlers[eid](data);
}
}
Macro defitions expand to
enum evID { eid1, eid2, eid3 };
void (*handlers[])(void*) = { handler1, handler2, handler3 };
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);
I am now reading a project and find some of the codes hard to understand, like below:
struct mcachefs_metadata_t* mdata_root;
...
mcachefs_metadata_release(mdata_root);
And the definition of mcachefs_metadata_release is as below:
void
mcachefs_metadata_release(struct mcachefs_metadata_t* mdata)
{
(void) mdata;
mcachefs_metadata_unlock ();
}
And the definitioin of mcachefs_metadata_unlock is as below:
#define mcachefs_metadata_unlock() mcachefs_mutex_unlock ( &mcachefs_metadata_mutex, "metadata", __CONTEXT );
Then, the mcachefs_mutex_unlock function:
void
mcachefs_mutex_unlock(struct mcachefs_mutex_t* mutex, const char* name,
const char* context)
{
int res;
...
mutex->owner = 0;
mutex->context = NULL;
res = pthread_mutex_unlock(&(mutex->mutex));
if (res == 0)
{
return;
}
...
}
I could not understand what does the (void) mdata; mean in the
mcachefs_metadata_release function. What does the usage of it?
It's for suppressing unused argument: mdata compiler warnings. Rather bad practice, by the way.
Say I have the following code:
struct test* t1;
t1 = get_t(1);
... where get_t is:
struct test* get_t(int);
How can I refactor the above code and put it in a function? Something like the following:
void r1(?* t, ?* (fn*)(int)) {
t = fn(1);
}
/* ... */
struct test* t1;
r1(t1, &get_t);
use void *param, a pointer to anything ... commonly used in glib as gpointer
I have two ideas:
[1] Pass void pointer to the variable/object, and type cast it in the function.
[2] Make a union of all datatypes along with an integer datatype which will identify which datatype variable in the union does hold the actual data. Pass this union as value or as void *
struct _unknown {
union {
int a;
float b;
char c;
double d;
} data;
int type;
} unknown;
.
.
.
if (unknown.type == FLOAT)
{
/* Process variable b */
}
else if (unknown.type == INT)
{
/* Process variable a */
}
.
.
.
Something like this.
You can hash define the FLOAT and INT and others as unique values.
Or simply
struct _unknown {
void *data;
int type;
} unknown;
.
.
.
if (unknown == FLOAT)
{
/* process (float *) data */
}
else if (unknown == INT)
{
/* process (int *) data */
}
else if (unknown == MY_DATA_TYPE)
{
/* process (my_data_type *) data */
/* where my_data_type could be a typedef, or struct */
}
If you have gcc, you can use this more typesafe version:
#define r1(varp,func) ({ \
typeof(**varp)* (*_func_)(int); \
typeof(**varp)* _varp_ = (varp); \
_func_ = (func); \
r1_((void**)(_varp_),(void*(*)(int))_func_); \
})
void r1_(void** varp,void*(*func)(int))
{
*varp = func(1);
}
Call as:
struct test* get_t(int);
struct test* t1;
r1(&t,get_t);
(You dont need to use & on functions, they decay to pointers automatically, like arrays). This checks that t is a pointer, and that get_t is a function returning that type of pointer. _varp_ is technically unneeded, but keeps the argument evaluation in the right order.
Edit:
If you don't have gcc, you can still do this, but you have to provide the type explicitly:
#define r1(T,varp,func) do { \
T*(*_func_)(int); \
T* _varp_ = (varp); \
_func_ = (func); \
r1_((void**)(_varp_),(void*(*)(int))_func_); \
} while(0)
void r1_(void** varp,void*(*func)(int))
{
*varp = func(1);
}
Call as:
struct test* get_t(int);
struct test* t1;
r1(struct test*,&t,get_t);
not quite as safe, and more redundant, but still fairly good.