I have a dynamic linked library in C++. What I want to do is have a callback function declared in the library and leave it to the user to define in their code that uses the library. Pseudo-code example:
//in library
void userDefinedFunction();
void libraryFunction() {
//do stuff
userDefinedFunction();
//do more stuff
}
//in user code
void userDefinedFunction() {
//user-specific code
}
Is this possible in modern C++?
Of course. Your library could accept a function pointer to a user defined function or a reference to a functor given by the user. The void libraryFunction() will just use that to call the user function.
You can use std::function from functional library. Here is an example with lambda expression and function
#include <iostream>
#include <functional>
std::function<int (int)> func;
int testfunc(int i)
{
std::cout<<"testfunc function called ";
return i+7;
}
void process()
{
if (func)
std::cout<<func(3)<<std::endl;
}
int main()
{
process();
func = [](int i) {
std::cout<<"Lambda function called ";
return i+4;
};
process();
func = testfunc;
process();
return 0;
}
Related
First post here and I've tried to look at previous similar posts but none of them seem to work or do quite what I want.
I have some C code, call it library.c. I've removed a lot of the code and simplified it.
// libary.c
// A callback function that takes an int
void (*library_cb)(int);
void init(void (*cb())) {
// some other code
library_cb = cb;
}
void sample() {
int data;
// execute a bunch of code and then call the callback function
(*library_cb)(data);
}
Now I have c++ code that defines the callback function that I want to pass to the code in library.c
// someclass.cpp
class SomeClass {
public:
SomeClass() {
};
~SomeClass() {
};
void callback(int data) {
// Do some stuff
}
};
And then in main.cpp I want to do something like
// main.cpp
extern "C" {
#include "library.h"
}
#include "someclass.h"
SomeClass some_class;
int main() {
init(&some_class.callback) // obviously doesn't work
while(true) {
sample(); // this would call callback in SomeClass
}
}
Now I know one solution is to define callback as
static void callback(int data)
But I was wondering if there are any other ways to do this. From what I read, std::function might help or std::mem_fn. But I can't seem to figure out how.
I haven't included the header files and I wrote this code as an example of my problem so there might be some syntax errors, but hopefully the question/goal is clear.
Edit:
I should have mentioned that I can edit the c library.
Reading the answers, it seems I can change the c library to also accept a void* pointer to the class object to get this to work. Could someone show me an example for this case please? I'm super new to interfacing c code with c++.
Passing a pointer to a C++ member function to a C API library
... is not possible.
From what I read, std::function might help or std::mem_fn
Neither of those can be called in C either, but keep reading 'till the end.
C only has regular non-member function pointers so those are the only function pointers that a C program can call. In C++, such pointer can point to either a free function or a static member function.
Within the C++ implementation of such static- or non-member function you can of course do anything within the power of C++ (although, letting an exception escape the function would be bad), so you can indeed call a non-static member function there.
But to call a non-static member function, there needs to be an instance. A static object is a trivial solution, but is not very flexible and only useful in a few situations.
Well designed callback API's in C let user of the API register a generic data pointer (i.e. void*) in addition to a function pointer, and that data pointer will be forwarded to the callback. This design allows the callbacks to be stateful - the state is stored in the pointed object. When using such C API, you can pass a pointer to an object whose member functions the callback can then call. Or, you could pass a data pointer to a std::function or some other stateful type erasing function wrapper, and use a generic free function that simply forwards the call to the wrapper.
Your C API is not very usable. Here's how I'd do it:
The callback must at least take a user-provided void* parameter that the library doesn't interpret in any way. Without this parameter, callbacks are useless. Yes, they really are useless and the users of your API users will hate you for that.
If you want the callback to be able to modify the value of its parameter, you can pass the address of the void* parameter. That is useful for e.g. allocation-on-registration and similar uses where the parameter changes during callback's execution. This makes the library completely decoupled from the use of the pointer: not only it doesn't interpret the pointer, but it doesn't keep its value constant.
The library API symbols are all prefixed to prevent collisions in the global namespace.
Typedefs are used as needed to ensure readable code. Typing out function pointer types is tedious at best.
The header is guarded against multiple-inclusion, i.e. it must be OK to include it multiple times in a translation unit, without any errors.
The header declares a C interface when compiled in a C++ translation unit, since, well: the interface is a C one. C++ mangles the symbol names and the header will declare binary-incompatible symbols.
The header declares the C interface noexcept in C++11. This presents optimization opportunities to the C++ users.
Consider the library registering more than one callback, as well as possibly invoking the callback on registration and deregistration: those make interoperation with other programming languages much easier.
library.h - usable from C and C++
#pragma once
#ifdef __cplusplus
extern "C" {
#pragma GCC diagnostic push
// clang erroneously issues a warning in spite of extern "C" linkage
#pragma GCC diagnostic ignored "-Wc++17-compat-mangling"
#endif
#ifndef LIBRARY_NOEXCEPT
#if __cplusplus >= 201103L
// c.f. https://stackoverflow.com/q/24362616/1329652
#define LIBRARY_NOEXCEPT noexcept
#else
#define LIBRARY_NOEXCEPT
#endif
#endif
enum library_register_enum { LIBRARY_REG_FAILURE = 0, LIBRARY_REG_SUCCESS = 1, LIBRARY_REG_DUPLICATE = -1 };
enum library_call_enum { LIBRARY_SAMPLE, LIBRARY_REGISTER, LIBRARY_DEREGISTER };
typedef enum library_register_enum library_register_result;
typedef enum library_call_enum library_call_type;
#if __cplusplus >= 201103L
void library_callback_dummy(library_call_type, int, void**) LIBRARY_NOEXCEPT;
using library_callback = decltype(&library_callback_dummy);
#else
typedef void (*library_callback)(library_call_type, int, void**);
#endif
void library_init(void) LIBRARY_NOEXCEPT;
library_register_result library_register_callback(library_callback cb, void *cb_param) LIBRARY_NOEXCEPT;
void library_deregister_callback(library_callback cb, void *cb_param) LIBRARY_NOEXCEPT;
void library_deregister_any_callback(library_callback cb) LIBRARY_NOEXCEPT;
void library_deregister_all_callbacks(void) LIBRARY_NOEXCEPT;
void library_deinit(void) LIBRARY_NOEXCEPT;
void library_sample(void) LIBRARY_NOEXCEPT;
#ifdef __cplusplus
#pragma GCC diagnostic pop
}
#endif
Below note that the private data and functions, i.e. those not part of the API, are declared so (static).
library.c - the implementation
#include "library.h"
#include <stdlib.h>
typedef struct callback_s {
struct callback_s *next;
library_callback function;
void *parameter;
} callback;
static callback *cb_head;
void library_init(void) { /* some other code */
}
void library_deinit(void) { library_deregister_all_callbacks(); }
library_register_result library_register_callback(library_callback cb, void *cb_param) {
callback *el = cb_head;
while (el) {
if (el->function == cb && el->parameter == cb_param) return LIBRARY_REG_DUPLICATE;
el = el->next;
}
el = malloc(sizeof(callback));
if (!el) return LIBRARY_REG_FAILURE;
el->next = cb_head;
el->function = cb;
el->parameter = cb_param;
cb_head = el;
cb(LIBRARY_REGISTER, 0, &el->parameter);
return LIBRARY_REG_SUCCESS;
}
static int match_callback(const callback *el, library_callback cb, void *cb_param) {
return el && el->function == cb && el->parameter == cb_param;
}
static int match_any_callback(const callback *el, library_callback cb, void *cb_param) {
return el && el->function == cb;
}
static int match_all_callbacks(const callback *el, library_callback cb, void *cb_param) {
return !!el;
}
typedef int (*matcher)(const callback *, library_callback, void *);
static void deregister_callback(matcher match, library_callback cb, void *cb_param) {
callback **p = &cb_head;
while (*p) {
callback *el = *p;
if (match(el, cb, cb_param)) {
*p = el->next;
el->function(LIBRARY_DEREGISTER, 0, &el->parameter);
free(el);
} else
p = &el->next;
}
}
void library_deregister_callback(library_callback cb, void *cb_param) {
deregister_callback(match_callback, cb, cb_param);
}
void library_deregister_any_callback(library_callback cb) {
deregister_callback(match_any_callback, cb, NULL);
}
void library_deregister_all_callbacks(void) {
deregister_callback(match_all_callbacks, NULL, NULL);
}
void library_sample(void) {
int data = 42;
// execute a bunch of code and then call the callback function
callback *el = cb_head;
while (el) {
el->function(LIBRARY_SAMPLE, data, &el->parameter);
el = el->next;
}
}
That way, the user registering the callback can pass arbitrary data to the callback. The library-using code would be implemented in C++ as follows:
// https://github.com/KubaO/stackoverflown/tree/master/questions/c-cpp-library-api-53643120
#include <iostream>
#include <memory>
#include <string>
#include "library.h"
struct Data {
std::string payload;
static int counter;
void print(int value) {
++counter;
std::cout << counter << ": " << value << ", " << payload << std::endl;
}
};
int Data::counter;
extern "C" void callback1(library_call_type type, int value, void **param) noexcept {
if (type == LIBRARY_SAMPLE) {
auto *data = static_cast<Data *>(*param);
data->print(value);
}
}
using DataPrintFn = std::function<void(int)>;
extern "C" void callback2(library_call_type type, int value, void **param) noexcept {
assert(param && *param);
auto *fun = static_cast<DataPrintFn *>(*param);
if (type == LIBRARY_SAMPLE)
(*fun)(value);
else if (type == LIBRARY_DEREGISTER) {
delete fun;
*param = nullptr;
}
}
void register_callback(Data *data) {
library_register_callback(&callback1, data);
}
template <typename F>
void register_callback(F &&fun) {
auto f = std::make_unique<DataPrintFn>(std::forward<F>(fun));
library_deregister_callback(callback2, f.get());
library_register_callback(callback2, f.release());
// the callback will retain the functor
}
int main() {
Data data;
data.payload = "payload";
library_init();
register_callback(&data);
register_callback([&](int value) noexcept { data.print(value); });
library_sample();
library_sample();
library_deinit(); // must happen before the 'data' is destructed
assert(data.counter == 4);
}
So this is confusing to explain, but I will try my best.
I have a function one of my classes that takes a function pointer as an argument, and what I would like to do is define the function as part of the argument. ie:
object->setFunctionPointer({string a = ""; return a;});
Is this possible? if so, what is the proper syntax of this?
In C++11, you can do it. You can use C++ lambda (anonymous functions).
See the sample code at http://ideone.com/8ZTWSU
#include <iostream>
using namespace std;
typedef const char * (*funcptr)();
funcptr s;
void setFuncPtr(funcptr t)
{
s = t;
}
int main() {
// your code goes here
setFuncPtr([]{return "Hello \n"; });
printf("%s\n", s());
return 0;
}
If we are talking about C++ you should use std::function and not function pointers. Unless you are interfacing with C APIs.
class Foo{
SetFunc(std::function<void(int)> func)
{
m_func = func;
}
private:
std::function<void(int)> m_func;
};
If your function is a member of a class, you cannot take an ordinary function pointer to store its address. What you need is a delegate; which are specialised function pointers for methods. Search the internet for C++ delegate and you should find numerous examples.
(Note: maybe there is an exception for static methods; I don't remember.)
Here is a complete example. Since c++11 this is the way to go:
#include<functional>
#include<string>
#include<iostream>
using namespace std;
class Object
{
public:
void setFunctionPointer(function<string(void)> function)
{
m_function = function;
}
string run()
{
return m_function();
}
private:
function<string(void)> m_function;
};
int main(int argc, char**argv)
{
Object *object = new Object;
object->setFunctionPointer([]{string a = "FOO"; return a;}); // here is the function assignment
cout << object->run() << endl;
delete object;
}
When run this prints FOO to stdout.
I have a series of callbacks, that doing some job with input data and then call next callback in that series. Look at this simple example (each callback in series increment and print the value):
#include <stdio.h>
//#include <boost/bind.hpp>
//#include <boost/function.hpp>
//typedef boost::function<void (int i)> DataCallback;
typedef void (*DataCallback)(int i);
class A
{
public:
DataCallback dataCallback;
void RegisterCallback(DataCallback callback);
void Callback(int i);
};
void A::RegisterCallback(DataCallback callback)
{
dataCallback = callback;
}
void A::Callback(int i)
{
dataCallback(++i);
printf("Callback. i = %i", i);
}
int main (void)
{
A a1, a2, a3;
//a1.RegisterCallback(boost::bind(&A::Callback, &a2));
//a2.RegisterCallback(boost::bind(&A::Callback, &a3));
a1.RegisterCallback(a2.Callback);
a2.RegisterCallback(a3.Callback);
a3.Callback(1);
return 0;
}
But I have a problem. In C++, you cannot use class member function as callbacks. As I know, solution of this problem is making callback function static. But in this case, I can't use in-class fields. To solve it, I can provide to callback pointer to class (this) and use it in callback. But, in my case, it mean, that I should provide to the lowest callback (a3.Callback) pointers to a2 and a1.
In my real project, I have about 6 callbacks and provide to 6th callbacks pointers to other 5 - is a bad idea, i think.
So, my question is - how to implement this series of callbacks?
As you can see in code, I tried to use boost::function and boost::bind, but MSVS2005 crashes on compile-time (Optimized Compiler has stoped working...) with warning C4180 at mem_fn.hpp#318. What is wrong here and is this the optimal way to solve my problem?
Yes, instead of callback, I'm now register ICallbackable class with Callback() method. Thank you for help.
#include <stdio.h>
class ICallbackable
{
public:
virtual void Callback(int i) = 0;
};
class A : public ICallbackable
{
public:
ICallbackable* dataCallback;
void RegisterCallback(ICallbackable* callback);
void Callback(int i);
};
void A::RegisterCallback(ICallbackable* callback)
{
dataCallback = callback;
}
void A::Callback(int i)
{
printf("Callback. i = %i\n", i);
if (dataCallback)
{
dataCallback->Callback(++i);
}
}
int main (void)
{
A a1, a2, a3;
a1.RegisterCallback(NULL);
a2.RegisterCallback(&a1);
a3.RegisterCallback(&a2);
a3.Callback(1);
return 0;
}
Before I present the code which is found at the bottom of this post I would like to talk about the issue and the fix's that I do not desire. Okay basically I've created a GUI from scratch sort of and one requirement I wanted for this was allow components to have their own click executions so if i click a button or tab etc.. It would call Component->Execute(); Well normally you would do something like a switch statement of ids and if that components ID equaled n number then it would perform this action. Well that seemed kinda dumb to me and I thought there has to be a better way. I eventually tried to incorporate a feature in JAVA where you would do like Component.AddActionListener(new ActionListener( public void execute(ActionEvent ae) { })); or something like that and I thought that this feature has to be possible in C++. I eventually came across storing void functions into a variable in which could be executed at any time and modified at any time. However I hadn't noticed an issue and that was this only worked with static functions. So below you'll see my problem. I've patched the problem by using a pointer to SomeClass however this would mean having an individual function call for every class type is there no way to store a function callback to a non-static class member without doing the below strategy? and instead doing a strategy like the commented out code?
//Main.cpp
#include <iostream> //system requires this.
#include "SomeClass.h"
void DoSomething1(void)
{
std::cout << "We Called Static DoSomething1\n";
}
void DoSomething2(void)
{
std::cout << "We Called Static DoSomething2\n";
}
int main()
{
void (*function_call2)(SomeClass*);
void (*function_call)() = DoSomething1; //This works No Problems!
function_call(); //Will Call the DoSomething1(void);
function_call = DoSomething2; //This works No Problems!
function_call(); //Will Call the DoSomething2(void);
SomeClass *some = new SomeClass(); //Create a SomeClass pointer;
function_call = SomeClass::DoSomething3; //Static SomeClass::DoSomething3();
function_call(); //Will Call the SomeClass::DoSomething3(void);
//function_call = some->DoSomething4; //Non-Static SomeClass::DoSomething4 gives an error.
//function_call(); //Not used because of error above.
function_call2 = SomeClass::DoSomething5; //Store the SomeClass::DoSomething(SomeClass* some);
function_call2(some); //Call out SomeClass::DoSomething5 which calls on SomeClass::DoSomething4's non static member.
system("pause");
return 0;
}
//SomeClass.hpp
#pragma once
#include <iostream>
class SomeClass
{
public:
SomeClass();
~SomeClass();
public:
static void DoSomething3(void);
void DoSomething4(void);
static void DoSomething5(SomeClass* some);
};
//SomeClass.cpp
#include "SomeClass.h"
SomeClass::SomeClass(void)
{
}
SomeClass::~SomeClass(void)
{
}
void SomeClass::DoSomething3(void)
{
std::cout << "We Called Static DoSomething3\n";
}
void SomeClass::DoSomething4(void)
{
std::cout << "We Called Non-Static DoSomething4\n";
}
void SomeClass::DoSomething5(SomeClass *some)
{
some->DoSomething4();
}
Secondary Fix for what I'll do not an exact answer I wanted but it meets my needs for now along with allowing additional features which would have become overly complicate had this not existed.
//Component.hpp
#pragma once
#include <iostream>
#include <windows.h>
#include <d3dx9.h>
#include <d3d9.h>
#include "Constants.hpp"
#include "ScreenState.hpp"
#include "ComponentType.hpp"
using namespace std;
class Component
{
static void EMPTY(void) { }
static void EMPTY(int i) { }
public:
Component(void)
{
callback = EMPTY;
callback2 = EMPTY;
callback_id = -1;
}
Component* SetFunction(void (*callback)())
{
this->callback = callback;
return this;
}
Component* SetFunction(void (*callback2)(int), int id)
{
this->callback_id = id;
this->callback2 = callback2;
return this;
}
void execute(void)
{
callback();
callback2(callback_id);
}
}
The syntax for pointers-to-member-functions is as follows:
struct Foo
{
void bar(int, int);
void zip(int, int);
};
Foo x;
void (Foo::*p)(int, int) = &Foo::bar; // pointer
(x.*p)(1, 2); // invocation
p = &Foo::zip;
(x.*p)(3, 4); // invocation
Mind the additional parentheses in the function invocation, which is needed to get the correct operator precedence. The member-dereference operator is .* (and there's also ->* from an instance pointer).
I have the following problem. I have a function from an external library (which cannot be modified) like this:
void externalFunction(int n, void udf(double*) );
I would like to pass as the udf function above a function member of an existing class. Please look at the following code:
// External function (tipically from an external library)
void externalFunction(int n, void udf(double*) )
{
// do something
}
// User Defined Function (UDF)
void myUDF(double* a)
{
// do something
}
// Class containing the User Defined Function (UDF)
class myClass
{
public:
void classUDF(double* a)
{
// do something...
};
};
int main()
{
int n=1;
// The UDF to be supplied is myUDF
externalFunction(n, myUDF);
// The UDF is the classUDF member function of a myClass object
myClass myClassObj;
externalFunction(n, myClassObj.classUDF); // ERROR!!
}
I cannot declare the classUDF member function as a static function, so the last line of the code above results in a compilation error!
This is impossible to do - in c++, you must use either a free function, or a static member function, or (in c++11) a lambda without capture to get a function pointer.
GCC allows you to create nested function which could do what you want, but only in C. It uses so-called trampolines to do that (basically small pieces of dynamically generated code). It would be possible to use this feature, but only if you split some of the code calling externalFunction to a separate C module.
Another possibility would be generating code at runtime eg. using libjit.
So if you're fine with non-reenrant function, create a global/static variable which will point to this and use it in your static function.
class myClass
{
public:
static myClass* callback_this;
static void classUDF(double* a)
{
callback_this.realUDF(a);
};
};
Its really horrible code, but I'm afraid you're out of luck with such a bad design as your externalFunction.
You can use Boost bind or TR1 bind (on recent compilers);;
externalFunction(n, boost::bind(&myClass::classUDF, boost::ref(myClassObj)));
Unfortunately, I lived in a pipe dream for the last 10 minutes. The only way forward is to call the target using some kind of a static wrapper function. The other answers have various neat (compiler-specific) tidbits on that, but here's the main trick:
void externalFunction(int n, void (*udf)(double*) )
{ double x; udf(&x); }
myClass myClassObj;
void wrapper(double* d) { myClassObj.classUDF(d); }
int main()
{
externalFunction(1, &wrapper);
}
std::function<>
Store a bound function in a variable like this:
std::function<void(double*)> stored = std::bind(&myClass::classUDF, boost::ref(myClassObj))
(assuming C++0x support in compiler now. I'm sure Boost has a boost::function<> somewhere)
Vanilla C++ pointers-to-member-function
Without magic like that, you'd need pointer-to-memberfunction syntax:
See also live on http://ideone.com/Ld7It
Edit to clarify to the commenters, obviously this only works iff you have control over the definition of externalFunction. This is in direct response to the /broken/ snippet int the OP.
struct myClass
{
void classUDF(double* a) { };
};
void externalFunction(int n, void (myClass::*udf)(double*) )
{
myClass myClassObj;
double x;
(myClassObj.*udf)(&x);
}
int main()
{
externalFunction(1, &myClass::classUDF);
}
C++98 idiomatic solution
// mem_fun_ref example
#include <iostream>
#include <functional>
#include <vector>
#include <algorithm>
#include <string>
int main ()
{
std::vector<std::string> numbers;
// populate vector:
numbers.push_back("one");
numbers.push_back("two");
numbers.push_back("three");
numbers.push_back("four");
numbers.push_back("five");
std::vector <int> lengths (numbers.size());
std::transform (numbers.begin(), numbers.end(), lengths.begin(),
std::mem_fun_ref(&std::string::length));
for (int i=0; i<5; i++) {
std::cout << numbers[i] << " has " << lengths[i] << " letters.\n";
}
return 0;
}
Here is how I do this, when MyClass is a singleton:
void externalFunction(int n, void udf(double) );
class MyClass
{
public:
static MyClass* m_this;
MyClass(){ m_this = this; }
static void mycallback(double* x){ m_this->myrealcallback(x); }
void myrealcallback(double* x);
}
int main()
{
MyClass myClass;
externalFunction(0, MyClass::mycallback);
}