I have a class and I want to set the class method as an argument of sigaction because I need to use some class attributes:
class MyClass {
void action(int sn, siginfo_t* t, void* ctx) {
...
}
};
int main() {
MyClass c;
struct sigaction sig_action;
sig_action.sa_sigaction = c.action; // ERROR!
}
Even I've tried to use std::bind with reinterpret_cast but didn't work.
So, how can I set sa_sigaction a class method?
NOTE: it SHOULD be a class method and not a static method or a function.
If you take a look at declaration of sigaction::sa_sigaction, you'll find that it is void (*)(int,siginfo_t*,void*). This is a pointer to function.
NOTE: it SHOULD be a class method and not a static method or a function.
It cannot be, because pointers to functions can not point to non-static member functions. You must pass a pointer to a non-member or a static member function as the signal handler. That function may in turn call the non-static member function if you so desire (as long as the function is async signal safe).
I need to use some class attributes
Make sure that those attributes are of type volatile sig_atomic_t.
class MyClass {
void action(int sn, siginfo_t* t, void* ctx) {
...
}
};
MyClass c;
void action(int sn, siginfo_t* t, void* ctx) {
c.action(sn, t, ctx);
}
int main() {
struct sigaction sig_action;
sig_action.sa_sigaction = action;
}
Related
I'm reading a lot of questions (and answers) about function pointers, functors and callbacks but I still have a confusion about which is the right tool for me.
Some of them cannot apply to my scenario because it seems my compiler avr-gcc v5.4.0 does not have C++ standard library (i.e. std::function is not available).
This is my base class:
class Debouncer
{
public:
typedef uint8_t (Debouncer::*debouncer_raw_t) (void);
Debouncer() {}
void setRawFunction(Debouncer::debouncer_raw_t callback) { _raw = callback; }
private:
debouncer_raw_t _raw;
void anotherFunction()
{
uint8_t value = _raw();
// do something
}
}
In my other classes I have:
class Inputs
{
public:
Inputs()
{
_deb.setRawFunction(myRaw);
}
private:
Debouncer _deb;
uint8_t myRaw()
{
return something;
}
}
Of course this won't compile because myRaw is not static.
Anyway, I'm going to try to avoid this because it would break the existing code.
If I'm not wrong, a lot of questions seem to ask the other way around.
Instead I just want to pass the pointer of my member function to my Debouncer class, so it can call _raw() when it needs to.
Here I found this advise to avoid std:: library:
#define CALL_MEMBER_FN(object, ptrToMember) ((object).*(ptrToMember))
void userCode(Fred& fred, FredMemFn p) // Use a typedef for pointer-to-member types
{
int ans = CALL_MEMBER_FN(fred,p)('x', 3.14);
// Would normally be: int ans = (fred.*p)('x', 3.14);
// ...
}
But it seems the other way around. Here the class Fred is my Debouncer.
I don't want to call the Debouncer member, but member of the caller class (i.e. Input::myRaw()).
Would you please help me to understand which is the right tool to achieve such a simple task?
Making a member function virtual is a relatively low-overhead way to have a single pointer (to an object) refer to both the object's data and the correct member function.
class InputsBase
{
// All classes that implement myRaw() should inherit from this class
public:
virtual uint8_t myRaw() = 0;
};
class Inputs : public InputsBase
{
public:
Inputs()
{
_deb.setRawFunction(this);
}
private:
Debouncer _deb;
virtual uint8_t myRaw()
{
return something;
}
}
Your Debouncer can then simply store a pointer to the object in question.
class Debouncer
{
public:
typedef InputsBase* debouncer_raw_t;
Debouncer() {}
void setRawFunction(debouncer_raw_t callback) { _raw = callback; }
private:
debouncer_raw_t _raw;
void anotherFunction()
{
uint8_t value = _raw->myRaw();
// do something
}
}
If you know (or require) each of the classes using Debouncer have a public myRaw() function (or better operator(), or actually anything else), the problem is simpler:
template <typename T>
class Debouncer
{
public:
Debouncer (T* t): _t(t) {}
void anotherFunction()
{
uint8_t value = _t->myRaw();
std::cout << static_cast<int>(value);
}
private:
T* _t;
};
class Inputs
{
public:
Inputs() : _deb(this)
{
// beware, if Debouncer uses its parameter in constructor (like call a method),
// you cannot use initializer list
}
uint8_t myRaw()
{
return 13;
}
void foo()
{
_deb.anotherFunction();
}
private:
Debouncer<Inputs> _deb;
};
int main()
{
Inputs i;
i.foo();
}
This would be preferred solution in C++. See for example standard library <algorithm> - any function taking a predicate or some other callable expects to call it with operator() rathen than having to deal with pointers-to-member-function.
If you don't know what function should be called and you really cannot impose any requirement on the classes, you need to store both a pointer (or reference) to the class and a pointer to the member function. Note that you cannot connect pointers to member functions of different classes, so we need templates once again:
template <typename T, typename Func>
class Debouncer
{
public:
Debouncer (T* t, Func f): _t(t), _f(f) {}
void anotherFunction()
{
uint8_t value = (_t->*_f)(); //I get it now why isocpp asks to use macro here, the syntax is horrible
std::cout << static_cast<int>(value);
}
private:
T* _t;
Func _f;
};
class Inputs
{
public:
Inputs() : _deb(this, &Inputs::myRaw)
{
// beware, if Debouncer uses its parameter in constructor (like call a method),
// you cannot use initializer list
}
uint8_t myRaw()
{
return 13;
}
void foo()
{
_deb.anotherFunction();
}
private:
Debouncer<Inputs, decltype(&Inputs::myRaw)> _deb; //decltype is C++11, you could also declare type like you did in your question
};
int main()
{
Inputs i;
i.foo();
}
I need to get a member function called by a standard function pointer, so I tried to abstract things like this:
class Sample {
public:
virtual void doSomething(void) = 0;
};
class A : public Sample {
void doSomething(void); // details omitted
};
class B : public Sample {
void doSomething(void); // details omitted
};
class Executor {
public:
Executor(Sample *sample)
: func(&sample->doSomething)
{
}
static void *execute(void *data) {
Executor *pX = data;
(pX->*func)(); // error invalid access of func from static function
(pX->*pX->func)(); // error pointer to member type 'void (Sample::)()'
// incompatible with object type 'Executor'
}
private:
void (Sample::*func)(void);
};
int main(void) {
A myA;
B myB;
Executor x0(&myA);
Executor x1(&myB);
externallyInvoke(&Executor::execute, &x0);
externallyInvoke(&Executor::execute, &x1);
}
externallyInvoke is a Linux system call, which takes a function pointer and a data pointer.
I'd like to use a static member function together with a this-pointer as data.
... and I don't want classes like A or B to have static members. So my idea was to create an interface like class Sample, that gets extended by A and B.
My problem is that I don't know how to invoke the pointer to member function from inside the Executor::execute function.
The problem is that you need two objects inside execute - one is the instance of Executor which will supply func, and the other is an instance of (a class derived from) Sample on which func will be invoked. So you have to store the object inside Executor, not the function:
class Executor {
public:
Executor(Sample *sample)
: obj(sample)
{
}
static void *execute(void *data) {
Executor *pX = static_cast<Executor*>(data);
pX->obj->doSomething();
}
private:
Sample *obj;
};
int main() { // note that `void main()` is not legal C++
A myA;
B myB;
Executor x0(&myA);
Executor x1(&myB);
externallyInvoke(&Executor::execute, &x0);
externallyInvoke(&Executor::execute, &x1);
}
A pointer to member function (such as your original void (Sample::*func)()) identifies a function within a class, but does not store the object. You'd still need to provide one to call the function.
If you want to interact with an external system call, you basically have to reinvent std::function yourself. No problem, here at Stack Overflow we're the masters of reinventing existing technology. So...
First, the interface:
struct FunctionStateBase
{
virtual ~FunctionStateBase() {}
virtual void Invoke() = 0;
};
extern "C" void InvokeAndDelete(void * data)
{
auto state = static_cast<FunctionStateBase *>(data);
state->Invoke();
delete state;
}
Here's how you use it:
externallyInvoke(&InvokeAndDelete, MakeFunction(&A::doSomething, &myA));
Now we need to implement MakeFunction:
template <typename> struct FunctionState;
template <typename C, typename R>
struct FunctionState<R (C::*)()> : FunctionStateBase
{
R (C::ptmf_*)();
C * obj_;
FunctionState(R (C::ptmf*)(), C * obj) : obj_(obj), ptmf_(ptmf) {}
virtual void Invoke() { (C->ptmf_)(); }
};
template <typename C, typename R>
FunctionState<R (C::*)()> MakeFunction(R (C::*ptmf)(), C * obj)
{
return new FunctionState<R (C::*)()>(ptfm, obj);
}
At this point we're managing the life time of the function wrapper manually, and note that InvokeAndDelete actually takes ownership of the function state. In proper C++, we would wrap the entire system call invocation in a class that would encapsulate the lifetime management internally.
You can add further specializations for member functions that take arguments; you just need to store a copy of the arguments in the state.
You'll need to also pass an instance ofSample on which to call the function (since it's a pointer to a member of Sample). There's a few ways to bring the instance along. You could make it a member of Executor, pass a std::pair* as data or you could combine the function pointer and the instance as a functor. Here's a lamda based approach for the latter. Lamda has the advantage of being more versatile. It's possible to do much more than just call one member of one class. As a bonus, this approach does not avoid visibility rules, although that means doSomething may not be private (or it must be called through the parent pointer).
template<class F>
class Executor {
F f;
public:
Executor(F f): f(f){}
static void *execute(void *data) {
Executor<F> *pX = static_cast<Executor<F>*>(data);
pX->f();
return this; // not quite sure what you intend to return, but just to make this a well formed function...
}
};
int main() {
A myA;
B myB;
auto callback0 = [myA]{
myA.doSomething();
};
auto callback1 = [myB]{
myB.doSomething();
};
Executor<decltype(callback0)> x0(callback0);
Executor<decltype(callback1)> x1(callback1);
externallyInvoke(&Executor::execute, &x0);
externallyInvoke(&Executor::execute, &x1);
}
I am developing a C++ application using a C library. I have to send a pointer to function to the C library.
This is my class:
class MainWindow : public QMainWindow {
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
private:
Ui::MainWindow *ui;
void f(int*);
private slots:
void on_btn_clicked();
};
This is my on_btn_clicked function:
void MainWindow::on_btn_clicked()
{
void (MainWindow::* ptfptr) (int*) = &MainWindow::f;
c_library_function(static_cast<void()(int*)>(ptfptr), NULL);
}
The C function should get a pointer to a such function : void f(int*).
But the code above doesn't work, I cannot succeed to convert my f member function to the desired pointer.
Can anybody please help?
You can't pass a non-static member function pointer as an ordinary function pointer. They're not the same thing, and probably not even the same size.
You can however (usually) pass a pointer to a static member function through C. Usually when registering a callback in a C API, you also get to pass a "user data" pointer which gets passed back to your registered function. So you can do something like:
class MyClass
{
void non_static_func(/* args */);
public:
static void static_func(MyClass *ptr, /* other args */) {
ptr->non_static_func(/* other args */);
}
};
Then register your callback as
c_library_function(MyClass::static_func, this);
i.e. pass the instance pointer to the static method, and use that as a forwarding function.
Strictly speaking for total portability you need to use a free function declared extern "C" rather than a static member to do your forwarding (declared as a friend if necessary), but practically speaking I've never had any problems using this method to interface C++ code with GObject code, which is C callback-heavy.
You can't pass a function pointer to a non-static member function. What you can do is to create a static or global function that makes the call with an instance parameter.
Here's an example I find useful which uses a helper class with two members: a function wrapper and a callback function that calls the wrapper.
template <typename T>
struct Callback;
template <typename Ret, typename... Params>
struct Callback<Ret(Params...)> {
template <typename... Args>
static Ret callback(Args... args) { return func(args...); }
static std::function<Ret(Params...)> func;
};
// Initialize the static member.
template <typename Ret, typename... Params>
std::function<Ret(Params...)> Callback<Ret(Params...)>::func;
Using this you can store any callable, even non-static member functions (using std::bind) and convert to a c-pointer using the Callback::callback function. E.g:
struct Foo {
void print(int* x) { // Some member function.
std::cout << *x << std::endl;
}
};
int main() {
Foo foo; // Create instance of Foo.
// Store member function and the instance using std::bind.
Callback<void(int*)>::func = std::bind(&Foo::print, foo, std::placeholders::_1);
// Convert callback-function to c-pointer.
void (*c_func)(int*) = static_cast<decltype(c_func)>(Callback<void(int*)>::callback);
// Use in any way you wish.
std::unique_ptr<int> iptr{new int(5)};
c_func(iptr.get());
}
If I recall it correctly, Only static methods of a class can be accessed via "normal" C pointer to function syntax. So try to make it static. The pointer to a method of a class needs extra information, such as the "object" (this) which has no meaning for a pure C method.
The FAQ shown here has good explanation and a possible (ugly) solution for your problem.
#Snps answer is great. I extended it with a maker function that creates a callback, as I always use void callbacks without parameters:
typedef void (*voidCCallback)();
template<typename T>
voidCCallback makeCCallback(void (T::*method)(),T* r){
Callback<void()>::func = std::bind(method, r);
void (*c_function_pointer)() = static_cast<decltype(c_function_pointer)>(Callback<void()>::callback);
return c_function_pointer;
}
From then on, you can create your plain C callback from within the class or anywhere else and have the member called:
voidCCallback callback = makeCCallback(&Foo::print, this);
plainOldCFunction(callback);
#Snps answer is perfect! But as #DXM mentioned it can hold only one callback. I've improved it a little, now it can keep many callbacks of the same type. It's a little bit strange, but works perfect:
#include <type_traits>
template<typename T>
struct ActualType {
typedef T type;
};
template<typename T>
struct ActualType<T*> {
typedef typename ActualType<T>::type type;
};
template<typename T, unsigned int n,typename CallerType>
struct Callback;
template<typename Ret, typename ... Params, unsigned int n,typename CallerType>
struct Callback<Ret(Params...), n,CallerType> {
typedef Ret (*ret_cb)(Params...);
template<typename ... Args>
static Ret callback(Args ... args) {
func(args...);
}
static ret_cb getCallback(std::function<Ret(Params...)> fn) {
func = fn;
return static_cast<ret_cb>(Callback<Ret(Params...), n,CallerType>::callback);
}
static std::function<Ret(Params...)> func;
};
template<typename Ret, typename ... Params, unsigned int n,typename CallerType>
std::function<Ret(Params...)> Callback<Ret(Params...), n,CallerType>::func;
#define GETCB(ptrtype,callertype) Callback<ActualType<ptrtype>::type,__COUNTER__,callertype>::getCallback
Now you can just do something like this:
typedef void (cb_type)(uint8_t, uint8_t);
class testfunc {
public:
void test(int x) {
std::cout << "in testfunc.test " <<x<< std::endl;
}
void test1(int x) {
std::cout << "in testfunc.test1 " <<x<< std::endl;
}
};
cb_type* f = GETCB(cb_type, testfunc)(std::bind(&testfunc::test, tf, std::placeholders::_2));
cb_type* f1 = GETCB(cb_type, testfunc)(
std::bind(&testfunc::test1, tf, std::placeholders::_2));
f(5, 4);
f1(5, 7);
The short answer is: you can convert a member function pointer to an ordinary C function pointer using std::mem_fn.
That is the answer to the question as given, but this question seems to have a confused premise, as the asker expects C code to be able to call an instance method of MainWindow without having a MainWindow*, which is simply impossible.
If you use mem_fn to cast MainWindow::on_btn_clicked to a C function pointer, then you still a function that takes a MainWindow* as its first argument.
void (*window_callback)(MainWindow*,int*) = std::mem_fn(&MainWindow::on_btn_clicked);
That is the answer to the question as given, but it doesn't match the interface. You would have to write a C function to wrap the call to a specific instance (after all, your C API code knows nothing about MainWindow or any specific instance of it):
void window_button_click_wrapper(int* arg)
{
MainWindow::inst()->on_btn_clicked(arg);
}
This is considered an OO anti-pattern, but since the C API knows nothing about your object, it's the only way.
I've got an idea (not entirely standard-compliant, as extern "C" is missing):
class MainWindow;
static MainWindow* instance;
class MainWindow
{
public:
MainWindow()
{
instance = this;
registerCallback([](int* arg){instance->...});
}
};
You will have problems if multiple instances of MainWindow are instantiated.
I have a question regarding callbacks using tr1::function. I've defined the following:
class SomeClass {
public:
typedef std::tr1::function<void(unsigned char*, int)> Callback;
void registerCallback(Callback);
private:
Callback callback;
}
I've defined another class:
class SomeOtherClass {
void myCallback(unsigned char*, int);
}
Now I want to register my function 'myCallback' as callback at class 'SomeClass'using the method 'registerCallback'. However, it is not working. I've had a look on the boost documentation on the function and it seems legit to use (member) methods of a class for callbacks. Am I wrong?
Thanks in advance!
Member functions have an implicit first parameter, a this pointer so as to know which object to call the function on. Normally, it's hidden from you, but to bind a member function to std::function, you need to explicitly provide the class type in template parameter.
#include <functional>
#include <iostream>
struct Callback_t {
void myCallback(int)
{
std::cout << "You called me?";
}
};
class SomeClass {
public:
SomeClass() : callback() { }
typedef std::function<void(Callback_t*, int)> Callback;
// ^^^^^^^^^^^
void registerCallback(const Callback& c)
{
callback = c;
}
void callOn(Callback_t* p)
{
callback(p, 42);
}
private:
Callback callback;
};
int main()
{
SomeClass sc;
sc.registerCallback(&Callback_t::myCallback);
Callback_t cb; // we need an instance of Callback_t to call a member on
sc.callOn(&cb);
}
Output: You called me?;
Why all this complicated mumbo-jumbo?
Why not create a class as thus (for example)
Class MouseOverEventCallBack
{
public:
virtual void RunMouseOverCallback() = 0;
};
Then just create classes that inherit this class (and redefine the method RunMouseOverCallback)
Then Register function just needs to be
void registerCallback(MouseOverEventCallBack *callbackObject); // possible could use a reference
The register method will just call the method and the object will have all that it needs.
Seems a bit simpler. Let the compiler do the work with pointers to functions etc.
the function void (*)(unsigned char*, int) is a free function, which is a different type from void (SomeOtherClass::*)(unsigned char*, int), thus the error. You need an object to call the latter, while the former is a free function.
Look at the possible solutions listed in the Boost documentation
Another possibility is that your SomeOtherClass::myCallback is private, so you do not have access to it.
Use templates:
template <class T>
class B
{
public:
typedef void (T::*TCallBackFunction)(void);
void SetCallBack(T* pCallBackClass, TCallBackFunction pCallBackFunction)
{
if(pCallBackFunction && pCallBackClass)
{
m_pCallBackFunction = pCallBackFunction;
m_pCallBackClass = pCallBackClass;
}
}
void StartCallBackFunction()
{
(pCallBackClass->(*m_pCallBackFunction))();
}
private:
TCallBackFunction m_pCallBackFunction;
T* m_pCallBackClass;
};
Such like this. And use it:
...
B<MyClass> b;
b.SetCallBack(&b, &MyClass::MyFunction);
...
So I'm working on this event management class. I'm storing a list of pointers to member functions of the signature void (Event*) where Event is just a struct that stores some random data at the moment.
typedef boost::function<void(Event*)> Callback;
typedef vector<Callback> CallbackList;
class EventManager
{
public:
template<typename T>
void RegisterEventHandler(const std::string& type, void (T::*handler)(Event*), T* obj)
{
mCallbackList[type].push_back(boost::bind(handler, obj, _1));
}
void DispatchEvent(const std::string& type, Event* evt)
{
for(CallbackList::iterator it = mCallbackList[type].begin(); it != mCallbackList[type].end(); ++it)
{
Callback callback = (*it);
callback(evt);
}
}
private:
hash_map<std::string, CallbackList> mCallbackList;
};
I'm wondering, if it's possible for me to derive different versions of Event, and pass pointers to those member functions into this class? Currently I'm trying this.
class MouseEvent : public Event
{
public:
int testMouseData1;
int testMouseData2;
int testMouseData3;
};
class HelloWorld
{
public:
void Display(MouseEvent* evt)
{
cout << "Hello, world!" << endl;
}
};
int main(void)
{
MouseEvent* evt = new MouseEvent();
HelloWorld* world = new HelloWorld();
eventManager->RegisterEventHandler("testType", &HelloWorld::Display, world);
return 0;
}
This gives me the following error in XCode.
error: no matching function for call to 'EventManager::RegisterEventHandler(const char [9], void (HelloWorld::*)(MouseEvent*), HelloWorld*&)'
Do you know how I can safely pass in a pointer that's expecting a derived class in its function signature? Thanks.
So I found a solution that seems to be working for me, but I'm not sure if it's entirely safe to do. I changed the RegisterEventHandler method to cast all of the function pointers that I send in to the same type...
template<typename T1, typename T2>
void RegisterEventHandler(const String& type, T1 handler, T2* obj)
{
void (T2::*evtHandler)(Event*) = (void (T2::*)(Event*)) (handler);
mCallbackList[type].push_back(boost::bind(evtHandler, obj, _1));
}
now it all seems to just work as I originally intended. But I'm pretty new to all this so I'm not entirely sure if this is a safe thing to do. Any thoughts? Thanks
If your prototype expects "Event" type then you need to make sure the void Display(MouseEvent* evt) function is accepting the "Event" type. So change it to void Display(Event *evt) Then inside the call you can typecast it back to a MouseEvent, assuming that the caller passed an actual MouseEvent, referenced as an "Event".
Secondly, I believe you may have some other issues with the way you are calling RegisterEventHandler since it is in a template but you are not specifying the template type.