Pass a c++ lambda to old c function pointer - c

I have to create a c++ wrapper to a old c library.
In a class method I must call a c function that takes with other stuff also a function pointer(it is a event handler and the function takes a function that is fired when a event happens).
A simple example of it is this:
void myclass::add_handler(std::function<void()> handler, otherstuff...)
{
/*
* Many things.
*/
type_of_function_pointer_accepted_by_old_c_library_add_handler nameofvariable =
[handler](same_arguments_as_in_definition_of_the_old_c_function_pointer_accepted)
{
/*
* Many other things with other stuff to be done before the
* handler but always only when fired and not when myclass::add_handler is called.
*/
handler();
};
old_c_library_add_handler(nameofvariable);
/*
* Last things.
*/
}
The compiler complains, as I know, that I can't assign a lambda with capture to an old c function pointer.
The question is: how can I do to solve?

Here is an example. We are using the fact that lambdas that do not capture anything are, according to the C++ standard, usable as function pointers.
/* The definition of the C function */
typedef void (*PointerToFunction)();
void old_c_function(PointerToFunction handler, void* context);
/* An example of a C++ function that calls the above C function */
void Foo(std::function<void()> handler)
{
auto lambda = [] (void* context) {
auto handler = reinterpret_cast<std::function<void()>*>(context);
(*handler)();
};
old_c_function(&lambda, &handler);
}
I believe you can use the same idea in your context.

Related

Pass delegates to external C functions in D

How do I pass a delegate to an external C function taking a function pointer, in D?
Let me cross post what I said on the newsgroup:
How do I pass a delegate to an external C function taking a
function pointer?
You can't do it directly in general, unless you can modify the C
function, then you can hack around it, but a delegate and a
regular function pointer are pretty different animals.
But perhaps you can magic hack it. Observe:
// a C function that needs a plain function
extern(C) void test(void function() f) {
// pretend this is implemented in C
f();
}
// just create a random delegate
void delegate() foo(int a) {
return { import std.stdio; writeln(a); };
}
// what we want to work
void main() {
auto dg = foo(10);
dg(); // works
//test(dg); // won't work
test(bindDelegate(dg)); // we want this
}
// transform delegate into pointer..
import std.traits;
auto bindDelegate(T, string file = __FILE__, size_t line = __LINE__)(T t) if(isDelegate!T) {
static T dg;
dg = t;
extern(C)
static ReturnType!T func(ParameterTypeTuple!T args) {
return dg(args);
}
return &func;
}
What bindDelegate does is create a special static variable and
function for that specific call. It is as if we wrote a separate
function and global to hold it.
The __FILE__, __LINE__ things are a filthy hack to make it
instantiate a separate variable+function pair for different
lines so the global variable holding the delegate won't be so
easily overwritten.

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.

How to invoke invalid handler function like gets_s() does?

I used the following code to invoke an invalid parameter handler if the user enters more than 4 characters.Actually it's the gets_s() function which invokes the handler.
...
char arr[5];
_invalid_parameter_handler newHandler;
newHandler = myInvalidParameterHandler;
_set_invalid_parameter_handler(newHandler);
gets_s(arr,4);
...
}
void myInvalidParameterHandler(const wchar_t* expression,const wchar_t* function,
const wchar_t* file,
unsigned int line,
uintptr_t pReserved)
{
...
}
Now, my question is how gets_s() calls/invokes the handler internally?I am asking this because I want to do something similar in my program.For eg. lets say I have a function declared like-
EDIT:
If when running the above code the user enters more than 4 characters then the handler is invoked.If I comment out the invalid handler related code then my program will crash.The same I want to achieve.
If some one uses my function he should get same behavior as I get when using gets_s.Please don't suggest this is good or bad.I just want to learn it.gets_s doesn't know which handler func I am gonna set.Similarly my function doesn't know which invalid handler func the user will set.I think there might be some C runtime global variable of type _invalid_parameter_handler which the '_set_invalid_parameter_handler()' func sets which gets_s uses.
In my opinion 1 and 3 are the same, and yes you could do it like that. Have all your functions call a function pointer in some global struct and you're set.
Set up a global object that contains a function pointer and some bookkeeping dat
When a function detects something wrong it can call the handler
But don't do it. It's way better to return an error status than to automatically call a function when something "feels" wrong. Then you can check the return status and act on it, instead of some automatic handler taking over.
EDIT
From your comment I believe you don't know about function pointers.
/* here is the handling function */
void handler(char *msg)
{
fprintf(stderr, "%s\n", msg);
}
void (*err_handler)
void some_function_like_gets(void *arg)
{
if (NULL == arg) {
(*err_handler)("Oh noes! You passed a NULL pointer :(");
return;
}
}
int main()
{
/* ... */
/* setting up handler */
err_handler = handler;
/* calling function */
some_function_like_gets(NULL);
/* ... */
}
EDIT 2
The sad part is that you downvoted this even though the MSDN page says:
[in] pNew The function pointer
to the new invalid parameter handler.

Mixing C functions in an Objective-C class

I am writing an Objective-C class but it uses an API written in C. This is mostly fine as mixing C calls with Objective-C calls causes few problems.
However one of the API call requires a call back method (example):
success = CFHostSetClient(host, MyCFHostClientCallBack, &context);
Where MyCFHostClientCallBack is a C function defined like this:
static void MyCFHostClientCallBack(CFHostRef host, CFHostInfoType typeInfo, const CFStreamError *error, void *info);
Can/How do I call an Objective-C method in place of this?
Can/Should I mix C functions with my Objective-C calls?
How do I mix C functions with Objective-C methods?
Mixing C and Objective-C methods and function is possible, here is a simple example that uses the SQLite API within an iPhone App: (course site)
Download the Zip file (09_MySQLiteTableView.zip)
C functions need to be declared outside of the #implementation in an Objective-C (.m) file.
int MyCFunction(int num, void *data)
{
//code here...
}
#implementation
- (void)MyObjectiveCMethod:(int)number withData:(NSData *)data
{
//code here
}
#end
Because the C function is outside of the #implementation it cannot call methods like
[self doSomething]
and has no access to ivars.
This can be worked around as long as the call-back function takes a userInfo or context type parameter, normally of type void*. This can be used to send any Objective-C object to the C function.
As in the sample code, this can be manipulated with normal Objective-C operations.
In addition please read this answer: Mixing C functions in an Objective-C class
To call Objective-C code from a C callback I would use something like:
void * refToSelf;
int cCallback()
{
[refToSelf someMethod:someArg];
}
#implementation SomeClass
- (id) init
{
self = [super init];
refToSelf = self;
}
- (void) someMethod:(int) someArg
{
}
Can/How do I call an Objective-C method in place of this?
You cannot.
Can/Should I mix C function in with my Objective-C call?
Yes. Write a C function and use that as the callback to the CF function.
How do I mix C function with Objective-C methods?
You can set self as the info pointer in your context structure. That will be passed to the callback. Then, in the callback, cast the info pointer back to id:
MyClass *self = (id)info;
You can then send self messages. You still can't directly access instance variables, though, since a C function is outside of the #implementation section. You'll have to make them properties. You can do this with a class extension. (Contrary to what that document says, you would not declare the extension inside #implementation, but in the same file with it, generally right above it.)
What I've always found helpful in this situation is to make an Obj-C wrapper on top of the C API. Implement what you need to using C functions, and build an Objective-C class (or two) on top of it, so that's all the outside world will see. For example, in the case of a callback like this, you might make a C function that calls Obj-C delegate methods on other objects.
.m call function inside .c:
CrifanLib.h
#ifndef CrifanLib_h
#define CrifanLib_h
#include <stdio.h>
void fileModeToStr(mode_t mode, char * modeStrBuf);
#endif /* CrifanLib_h */
CrifanLib.c
#include "CrifanLib.h"
#include <stdbool.h>
void fileModeToStr(mode_t mode, char * modeStrBuf) {
// buf must have at least 10 bytes
const char chars[] = "rwxrwxrwx";
for (size_t i = 0; i < 9; i++) {
// buf[i] = (mode & (1 << (8-i))) ? chars[i] : '-';
bool hasSetCurBit = mode & (1 << (8-i));
modeStrBuf[i] = hasSetCurBit ? chars[i] : '-';
}
modeStrBuf[9] = '\0';
}
called by Objective-C's .m:
#include “CrifanLib.h"
#interface JailbreakDetectionViewController ()
#end
#implementation JailbreakDetectionViewController
…
char* statToStr(struct stat* statInfo){
char stModeStr[10];
fileModeToStr(statInfo->st_mode, stModeStr);
...
}
...
done.

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