C passing structure to a callback function (Tizen) - c

I'm writing an app for Tizen (smart watches). Can't pass a structure to a callback.
My typedef:
typedef struct _Health {
...;
const char *data;
} health_s;
Declaring a structure and initializing it:
health_s health = {
...,
.data = "steps"
};
Passing it to a function:
_app_check_and_request_permission("http://tizen.org/privilege/healthinfo", &health);
Getting and checking if the struct address passed well:
void _app_check_and_request_permission(const char *privilege, void *user_data)
{
health_s *p_health = user_data;
dlog_print(DLOG_INFO, LOG_TAG, "Health data: %s", p_health->data);
...
And here I see in the log "Health data: steps". Passed well. Then I'm trying to pass user_data to a callback function
...
ppm_request_permission(privilege, _app_request_response_cb, p_health);
}
From function description in Tizen docs:
...
* #param[in] user_data User specific data which will be passed to
* the given callback.
int ppm_request_permission(const char *privilege,
ppm_request_response_cb callback,
void *user_data);
Callback declaration:
static void _app_request_response_cb(ppm_call_cause_e cause, ppm_request_result_e result,
const char *privilege, void *user_data);
And in the callback I'm getting Health data: NULL. Tried to pass p_health->data to the callback and that's ok. The problem is with passing the whole structure.
What am I doing wrong? Thanks.
Update:
Checked the addresses of the passed structure in the _app_check_and_request_permission function and in the callback and they are the same. But the struct in the callback is still empty...

Probably the lifetime of health has ended before _app_request_response_cb is called by the system on completion of the request. This is, for example, the case if the shown definition of health is contained in a function which returns before the request completes. Simple remedy: define health with storage class static.

Related

How to let the user bind a click handler function to a button?

I am currently building my own GUI using the SDL2 library for a program i wrote in C (c89).
Problem
I want to let the user of my code pass its own click handler function, which would be called every time a click event is fired on the surface of the corresponding button.
What I tried
I thought i could use function pointers like this :
bind_ClickHandler(void (*function)(void)) {/* bind it to a button */}
but, obviously, it is too limiting for the user.
So i tried to use stdarg.h :
/* ... : arguments to pass to the click handler */
bind_ClickHandler(void (*function)(), int nb_args, ...)
{
void *arg_pt;
va_list args;
va_start(args, nb_args);
/* I don't know what to do so i cast it as a garbage pointer */
arg_pt = va_arg(args, void *);
/* repeat this in a loop to save the args and bind the click handler to a button */
}
With this code i can pass arguments to the click handler, but only if i know their types.
What I want
I want to use something like the second piece of code i showed you to save the args to pass to the click handler, but it doesn't work because i need to know the types of the args to use va_arg().
Just pass a single void* pointer. Like qsort_r or pthread_create[*]. The user only needs one pointer - and that pointer will point anywhere the user wants to.
void (*clickhandler_user_function)(void *) = NULL;
void *clickhandler_user_function_arg = NULL;
void bind_ClickHandler(void (*function)(void*arg), void *function_arg) {
// store function and fucntion_arg somewhere
clickhandler_user_function = function;
clickhandler_user_function_arg = function_arg;
}
A single pointer is just enough:
struct user_context_s {
int some_number;
const char *some string;
// etc.
};
void user_function_that_operates_on_user_context(void *p) {
struct user_context_s *ctx = p;
printf("My number is: %d\n", ctx->some_number);
}
int main() {
// user can use malloc() and manage the lifetime of it's context
struct user_context_s ctx = {1, "blabla"};
bind_ClickHandler(user_function_that_operates_on_user_context, &user_context);
}
[*] - or thrd_create or fopencookie uses void *cookie or the standard sigevent uses void *sival_ptr; in sigval to pass context when sigev_notify == SIGEV_THREAD.

Wrapping function pointer

I am trying to wrap a library for porting purpose. The library exposes a function say -
fooLib(int , char , function pointer A);
signature of the function pointer A is
void handler(DataFormat);
where DataFormat is a struct
I don't want my wrapper to expose this library's callback function. I want to create a different function that should be used by the consumers of my wrapper, say
int handlerNew(NewDataFormat);
where NewDataFormat is my struct
The question now is how can I link these two functions? Whenever the library calls handler I want it to call my callback handlerNew after filling up the NewDataFormat struct from the DataFormat.
As long as you don't need thread safety, this is not hard. You just have to provide a private (static) handler with the library's interface that transforms the library data struct into your wrapped version, then calls your callback with that as an argument. Your interface will look like:
// wrapped_foo_lib.h
typedef struct { ... } NewDataFormat;
typedef void (*WRAPPED_CALLBACK)(NewDataFormat);
void wrappedFooLibCall(int x, char c, WRAPPED_CALLBACK cb);
Your implementation, which the client never gets to see is:
// wrapped_foo_lib.c
// This static var makes this module _not_ thread safe.
static WRAPPED_CALLBACK wrapped_callback;
static void private_handler(DataFormat data) {
NewDataFormat new_data = ...; // extract new_data from data
wrapped_callback(new_data);
}
void wrappedFooLibCall(int x, char c, WRAPPED_CALLBACK cb) {
wrapped_callback = cb;
foo_lib(x, c, private_handler);
}
The non-thread safety is why every API callback should include a void * that you get to define, which is passed on to the callback. I.e. your furnished library should be defined as
fooLib(int, char, void (*)(DataFormat, void *env));
void handler(DataFormat, void *env);
Now when you call fooLib, you furnish any struct at all as env, and it's passed back to you. This way you can dispense with the static variable in the wrapper:
// wrapped_foo_lib.c
typedef struct { WRAPPED_CALLBACK wrapped_callback; } ENV;
static void private_handler(DataFormat data, void *void_env) {
ENV *env = (ENV*)void_env;
NewDataFormat new_data = ...; // extract new_data from data
env->wrapped_callback(new_data);
}
void wrappedFooLibCall(int x, char c, WRAPPED_CALLBACK cb) {
ENV env[1] = {{ cb }};
foo_lib(x, c, env);
}
This is thread safe because ENV is stack allocated. A nice example of this done well is the libpng.
Feel free to update the C90 to more modern syntax.

Store extra data in a c function pointer

Suppose there is a library function (can not modify) that accept a callback (function pointer) as its argument which will be called at some point in the future. My question: is there a way to store extra data along with the function pointer, so that when the callback is called, the extra data can be retrieved. The program is in c.
For example:
// callback's type, no argument
typedef void (*callback_t)();
// the library function
void regist_callback(callback_t cb);
// store data with the function pointer
callback_t store_data(callback_t cb, int data);
// retrieve data within the callback
int retrieve_data();
void my_callback() {
int a;
a = retrieve_data();
// do something with a ...
}
int my_func(...) {
// some variables that i want to pass to my_callback
int a;
// ... regist_callback may be called multiple times
regist_callback(store_data(my_callback, a));
// ...
}
The problem is because callback_t accept no argument. My idea is to generate a small piece of asm code each time to fill into regist_callback, when it is called, it can find the real callback and its data and store it on the stack (or some unused register), then jump to the real callback, and inside the callback, the data can be found.
pseudocode:
typedef struct {
// some asm code knows the following is the real callback
char trampoline_code[X];
callback_t real_callback;
int data;
} func_ptr_t;
callback_t store_data(callback_t cb, int data) {
// ... malloc a func_ptr_t
func_ptr_t * fpt = malloc(...);
// fill the trampoline_code, different machine and
// different calling conversion are different
// ...
fpt->real_callback = cb;
fpt->data = data;
return (callback_t)fpt;
}
int retrieve_data() {
// ... some asm code to retrive data on stack (or some register)
// and return
}
Is it reasonable? Is there any previous work done for such problem?
Unfortunately you're likely to be prohibited from executing your trampoline in more and more systems as time goes on, as executing data is a pretty common way of exploiting security vulnerabilities.
I'd start by reporting the bug to the author of the library. Everybody should know better than to offer a callback interface with no private data parameter.
Having such a limitation would make me think twice about how whether or not the library is reentrant. I would suggest ensuring you can only have one call outstanding at a time, and store the callback parameter in a global variable.
If you believe that the library is fit for use, then you could extend this by writing n different callback trampolines, each referring to their own global data, and wrap that up in some management API.

libevent API: understanding the pointer parameters or return values

for the following libevent API:
void event_set(struct event *ev, int fd, short event, void (*cb)(int, short, void *), void *arg)
event_add(struct event *ev, const struct timeval *timeout);
struct event* event_new (struct event_base *, evutil_socket_t, short, event_callback_fn, void)
I want to know:
1) for pointer parameter ev in the second function event_add, the function event_add makes a local copy of the ev structure or not?
for example, if I do something like:
code snippet 1:
struct event ev;
event_set(&ev, ..para list 1...); // event 1
event_add(&ev, ...);
event_set(&ev, ..para list 2...); // event 2
event_add(&ev, ...);
event 1 is different from event 2 because parameter list 1 is different from parameter list 2. if event_add makes a local copy, then it is no problem, but if event_add doesn't make a local copy, then these two event_add actually add only event 2?
besides, if I have a main function:
void func(){
struct event ev;
event_set(&ev, ...);
event_add(&ev, ...)
}
int main(){
func();
event_base_dispatch(base);
}
after func() is called, the execution returns to main(). since ev is a local variable inside func(). if event_add(&ev,...) doesn't make a local copy, then ev is nowhere to find and there will be a problem.
so can I call event_add() on a local event structure?
I want to add many timer events(use something like evtimer_set) from time to time, and the adding happens in some callback functions. so I can't define global variabbles for the timeout events in advance, if event_add() can't be called on local variables, are there any solutions for this?
2) event_new returns a structure pointer, I want to know where is the structure, it is in a stack/heap memory or static memory?
MY special case::
in the main.c
int main(){
struct event_base *base;
struct event pcap_ev;
..... // here I get a file descriptor pcapfd
event_set(&pcap_ev, pcapfd, EV_READ|EV_PERSIST, on_capture, pcap_handle);
event_base_set(base, &pcap_ev);
event_add(&pcap_ev, NULL);
.....
event_base_dispatch(base);
}
on_capture callback function:
void *on_capture(int pcapfd, short op, void *arg)
{
pcap_t *handle;
handle = (pcap_t *)arg;
fqueue_t* pkt_queue;
pkt_queue = init_fqueue();
pcap_dispatch(handle, -1, collect_pkt, pkt_queue); // this function put all the cached packets into pkt_queue
process_pcap(pkt_queue);
}
the sub-routine process_pcap():
void process_pcap(pkt_queue);{
for (pkt in pkt_queue){ // here is pseudo code
insert(table, pkt); // here insert the pkt into a certain table
struct event pkt_ev;
evtimer_set(&pkt_ev, timer_cb, NULL); // I want to call timer_cb after timeout
event_base_set(base, &pkt_ev);
event_add(&pkt_ev, timeout);
}
}
the callback function timer_cb():
timer_cb(...){
if(...) delete(table, pkt);
.......
}
I'm just afraid timer_cb() won't be called because pkt_ev is a local variable.
You must use a different struct event instance for each event you want to know about. You can only call event_add() on a local struct event variable if that variable has a lifetime that spans across all calls to the event loop API up until it is removed with event_del().
The allocation functions default to the heap, but you can substitute your own allocation routines in its place with event_set_mem_functions().

Function pointers and callbacks in C

I have started to review callbacks. I found this link on SO:
What is a "callback" in C and how are they implemented? It has a good example of callback which is very similar to what we use at work. However, I have tried to get it to work, but I have many errors.
#include <stdio.h>
/* Is the actual function pointer? */
typedef void (*event_cb_t)(const struct event *evt, void *user_data);
struct event_cb
{
event_cb_t cb;
void *data;
};
int event_cb_register(event_ct_t cb, void *user_data);
static void my_event_cb(const struct event *evt, void *data)
{
/* do some stuff */
}
int main(void)
{
event_cb_register(my_event_cb, &my_custom_data);
struct event_cb *callback;
callback->cb(event, callback->data);
return 0;
}
I know that callbacks use function pointers to store an address of a function. But there are a few things that I find I don't understand:
What is meant by "registering the callback" and "event dispatcher"?
This code compiles and runs under GCC with -Wall.
#include <stdio.h>
struct event_cb;
typedef void (*event_cb_t)(const struct event_cb *evt, void *user_data);
struct event_cb
{
event_cb_t cb;
void *data;
};
static struct event_cb saved = { 0, 0 };
void event_cb_register(event_cb_t cb, void *user_data)
{
saved.cb = cb;
saved.data = user_data;
}
static void my_event_cb(const struct event_cb *evt, void *data)
{
printf("in %s\n", __func__);
printf("data1: %s\n", (const char *)data);
printf("data2: %s\n", (const char *)evt->data);
}
int main(void)
{
char my_custom_data[40] = "Hello!";
event_cb_register(my_event_cb, my_custom_data);
saved.cb(&saved, saved.data);
return 0;
}
You probably need to review whether the call back function gets the whole struct event_cb or not - usually, you'd just pass the data because, as demonstrated, otherwise you have two sources of the same information (and a spare copy of the pointer to the function that you're in). There is a lot of cleanup that can be done on this - but it does work.
A question in the comments asks: Is this a good example of a callback?
Succinctly, no - but in part because there isn't sufficient infrastructure here.
In a sense, you can think of the comparison function passed to the qsort() or bsearch() functions as a callback. It is a pointer to a function that is passed into the generic function that does what the generic function cannot do for itself.
Another example of a callback is a signal handler function. You tell the system to call your function when the event - a signal - occurs. You set up the mechanisms ahead of time so that when the system needs to call a function, it knows which function to call.
The example code is attempting to provide a more elaborate mechanism - a callback with a context. In C++, this would perhaps be a functor.
Some of the code I work with has very fussy requirements about memory management - when used in a particular context. So, for testing, I use malloc() et al, but in production, I have to set the memory allocators to the specialized allocators. Then I provide a function call in the package so that the fussy code can override the default memory allocators with its own surrogate versions - and provided the surrogates work OK, the code will behave as before. Those are a form of callback - again, a form that does not need much (or anything) in the way of user context data.
Windowing systems have event handlers (callbacks) that are registered and that the GUI main event loop will call when events occur. Those usually need user context as well as the event-specific information provided by the GUI system.
What is meant by "registering the callback" and "event dispatcher"?
"registering the callback" is the act of telling the underlying system which precise function to call, and (optionally) with which parameters, and possibly also for which particular class of events that callback should be invoked.
The "event dispatcher" receives events from the O/S (or GUI, etc), and actually invokes the callbacks, by looking in the list of registered callbacks to see which are interested in that event.
Without the compiler output it's hard, but I can see a few problems;
int event_cb_register(event_ct_t cb, void *user_data);
Should be
int event_cb_register(event_cb_t cb, void *user_data);
The my_custom_data variable does not exist when it's used here;
event_cb_register(my_event_cb, &my_custom_data);
This pointer is never initialized;
struct event_cb *callback;
And in;
callback->cb(event, callback->data);
You cannot pass the name of a type ('event') to a function, you must pass an instance of that type.
int event_cb_register(event_ct_t cb, void *user_data);
What is that type event_ct_t? Do you mean event_cb_t?
struct event_cb *callback;
Creates an uninitialized pointer to a structure event_cb. Note mostly this points to garbage.
callback->cb(event, callback->data);
You are trying to call garbage. You need initialization:
struct event_cb callback;
callback.cb = my_event_cb;
callback.data = 42;
or some such stuff.
Registering a callback means that you are specifying which function should be called when the event of interest occurs. Basically you are setting the function pointer when registering a callback.
You created a pointer of the struct you declared, but it does not point to anything:
struct event_cb *callback;
You should just create a type of your struct:
struct event_cb callback;
and then pass its address to the functions.

Resources