I need to pass a pointer to a member function as an argument to a member function in another class. What I'm doing is something like below.
I want to call int Processor::AddJob(void (_pFunc)(void*), void* _pArg) method with void* ProcessHandler::Task(void* a) as the first argument.
I did it as
TaskFunc pFunc1 = &ProcessHandler::Task;
p_Processor->AddJob(pFunc1,10);
But it gives the error
error: no matching function for call to Processor::AddJob(void*
(ProcessHandler::&)(void), int)’ Processor.h:47: note: candidates
are: int Processor::AddJob(void* ()(void), void*)
Can someone please help me on this.My implementation is as follows.(Not the exact code-it is much larger than this)
class Processor
{
public:
Processor();
virtual ~Processor();
int AddJob(void *(*_pFunc)(void*), void* _pArg);
};
int Processor::AddJob(void *(*_pFunc)(void*), void* _pArg)
{
//Job addition related code goes here
}
/////////////////////////////////////////////////////////////////////////////
typedef void* (ProcessHandler::*TaskFunc)(void*);
class ProcessHandler
{
public:
ProcessHandler(Processor* _pProcessor);
virtual ~ProcessHandler();
void* Task(void* a);
void Init();
private:
Processor* p_Processor;
};
void* ProcessHandler::Task(void* a)
{
//Task related code goes here
}
void ProcessHandler::Init()
{
TaskFunc pFunc1 = &ProcessHandler::Task;
p_Processor->AddJob(pFunc1,10); //This give the compile error.
}
/////////////////////////////////////////////////////////////////////////
int main()
{
Processor* pProcessor = new Processor();
ProcessHandler* pProcessHandler = new ProcessHandler(pProcessor);
pProcessHandler->Init();
}
You can only pass static member functions via the address-of operator. Regular member functions don't work. You should consider using std::function.
In C++ I would suggest to do_NOT use pointers to functions(raw pointers are arguable too).
You should use std::function(boost::function) for more generality, or
template. Latter gives you a bit perfomance, but less typecheck.
void (_pFunc)(void*) is a C-Function pointer, and as such, you can only either pass C-Functions via that pointer, or static functions.
void (ProcessHandler::*)(void); //Since you already have a Typedef, pass that as 'type'
should help you call a member function.
Call it with the pointer to member function calling syntax:
(objectPointer->*functionPointer)();
Related
I want to be able to use a member variable to hold the address a function to call
I got the error:
cannot convert 'void (TestClass::*)(bool)' to 'void (*)(bool)' in
assignment
TestClass.cpp
#include "TestClass.h"
TestClass::TestClass()
{
_myFctPtr = &setFired;
}
void TestClass::setFired(bool isFired)
{
_fired = isFired;
}
void TestClass::updateValue()
{
(_myFctPtr)(true);
}
bool TestClass::getFired()
{
return _fired;
}
TestClass.h
#pragma once
class TestClass
{
private:
bool _fired = false;
protected:
void (*_myFctPtr)(bool);
public:
TestClass();
void setFired(bool);
void updateValue();
bool getFired();
};
The error:
cannot convert 'void (TestClass::*)(bool)' to 'void (*)(bool)' in assignment
Is showing you that pointers to class member functions have a different type from regular function pointers. This is because, in addition to the regular function arguments and return type, these functions are differentiated by the object they are called on (i.e. their this), which must be provided when invoking them.
Specifically, for a pointer to a function on TestClass which accepts a bool argument as shown here, you need to to define your field as the type void (TestClass::*)(bool):
void (TestClass::*_myFctPtr)(bool);
You can call this like so, assuming you want to invoke the method on this:
((this).*(_myFctPtr))(true);
This article provides additional useful information and advice on better, cleaner ways to invoke pointers to member functions - e.g. using std::invoke for cleaner syntax than what I provided above - but this is the bare minimum to quickly solve your issue.
I have method
typedef void
(* JSErrorReporter)(JSContext *cx, const char *message, JSErrorReport *report);
JS_SetErrorReporter(JSContext *cx, JSErrorReporter er);
I would like to pass object's method rather than static method
JS_SetErrorReporter(cx,this->Reporter);//Failed !
where Reporter is object's method (not static)
JS_SetErrorReporter(cx,Reporter); //Passed
where Reporter is static method , declare as
static void SomeClass::reportError(JSContext *cx, const char *message, JSErrorReport *report)
You want to use a member function pointer, you will have to get the syntax right, (not trivial)
For a boring function, taking and returning an int, that would be:
declaring a variable (also good for parameters):
int (SomeClass::*my_memfunc_ptr)(int);
assigning a variable:
my_memfunc_ptr = &SomeClass::some_member_func;
calling:
SomeClass *x = new SomeClass;
int n = (x->*my_memfunc_ptr)(6);
I leave adapting this to your non-int uses to you.
You can't do it directly. Because to call some non-static function you have to have this pointer but you don't pass it to JS_SetErrorReporter function.
Two possible solutions:
Change JSErrorReporter signature to accept +1 parameter of type void * and pass this pointer there.
Create a wrapper function as a global function, that also know required this pointer.
well avoid static function is easy use __closure function pointers instead:
//---------------------------------------------------------------------------
class C2
{
public:
void callback1() {} // your member function to pass to ...
};
class C1 // some class with member function pointer usage
{
public:
void (__closure *callback1)(); // member function pointer
C1() { callback1=NULL; } // constructor
void do_something() // some function with use of callback1
{
if (callback1) callback1();
}
};
void some_function(void (__closure *f)()) // some function with member function parameter usage
{
if (f) f();
}
void main()
{
C1 c1;
C2 c2;
c1.callback1=c2.callback1;
c1.do_something();
some_function(c1.callback1);
some_function(c2.callback1);
}
//---------------------------------------------------------------------------
[edit 1]
but as RichardPlunkett outlined __closure it is just for borland/embarcadero compilers
for VC/GCC/Intel ... compilers you need a workaround
there are some out there.
it looks like people prefer something called boost library
here i found an example of __closure mimic http://www.rsdn.ru/forum/cpp/3078740.flat
its in Russian but the source code is pretty clear even for us azbuka non-readers...
I have 2 classes
class B {
public:
int func(int i);
};
class A {
public:
typedef int (B::*fPtr)(int);
void run();
B* mB;
};
void A::run() {
// create a pointer
fPtr p = &(B::func);
// invoke the function
mB->*p(2); <------- Compilation Error
}
What i need is to create a pointer to func() in A's run function. I get a compilation error saying that mB is not corresponding to a function with 1 argument.
please help
You need to put parentheses around the function expression:
(mB->*p)(2);
But as others have pointed out, there's almost certainly a better way to do what you're trying to do.
Instance methods on a class always have a hidden first parameter for the this pointer, thus it is incompatible with your function pointer typedef. There is no way directly to obtain a pointer to a member function. The typical workaround is to use a "thunk" where you pass a static function that accepts a generic "catch all" parameter (such as void *) which can be statically cast to a pointer of your choosing on which you can invoke the member function. Example:
class B
{
public:
static void MyThunk(void * obj)
{
static_cast<B *>(obj)->MyRealFunc();
}
void MyRealFunc()
{
// do something here
}
// . . .
};
You can get a pointer to the static function easily as it has no 'hidden this', just reference it using B::MyThunk. If your function requires additional parameters, you can use something like a functor to capture the necesssary parameters and state.
You should definitely read this C++ FAQ Lite page which tells you much more about all this: Pointers to member functions
why can you not call mB->func(2);?
If you need different functions for B perhaps look into virtual functions and class inheritance
my rusty C++ skills got a fail after:
#include <pcap.h>
...
void Sniff::pcap_listen() {
pcap_t *loc;
char *dev;
dev = pcap_lookupdev(errbuf);
loc = pcap_open_live(dev,BUFSIZ,0,-1,errbuf);
pcap_loop(loc,-1,pcap_callback,NULL);
}
error: argument of type ‘void
(Sniff::)(u_char*, const pcap_pkthdr*,
const u_char*)’ does not match ‘void
(*)(u_char*, const pcap_pkthdr*, const
u_char*)’
Adding/removing 'static' definition in .h: no effect.
++ another problem:
listener = g_thread_create(pcap_listen, NULL, FALSE, NULL);
Lot of variations of ::, &, this .. was tested, most informative message was:
src/main.cpp:281: error: argument of
type ‘void* (Sniff::)(void*)’ does not
match ‘void* ()(void*)’
You can't pass a pointer to a member function to something that's expecting a function pointer. Fundamentally a pointer to a member function is a completely different type than a function pointer. There is no trivial conversion between the two and can never be one as there's no this pointer, which is required to call a non-static member function.
Simply adding static doesn't technically solve the problem either, since it won't have C linkage, which could be a problem with a conforming implementation. In most implementations this is well behaved, but it is not portable in general and the portable solution requires using
extern "C" {
void my_callback() {
}
}
Update:
Given that both of the functions you're trying to call seem to take a void* "user argument" you can use this with a variable to pass a pointer to an instance of your class, e.g. something along these lines:
class CallbackHandler {
public:
void my_callback();
};
extern "C" {
void callback_wrapper(void *arg) {
static_cast<CallbackHandler*>(arg)->my_callback();
}
}
void start_pcap_listen(CallbackHandler* receiver) {
pcap_t *loc;
char *dev;
dev = pcap_lookupdev(errbuf);
loc = pcap_open_live(dev,BUFSIZ,0,-1,errbuf);
pcap_loop(loc,-1,callback_wrapper,receiver);
}
It's not pretty, but it works.
Member function and "free" function pointers are not interchangeable in C++. Your pcap_callback function appears to be an instance (non-static) member of class Sniff. If it is a static member, then you have to qualify it with the class name.
pcap_loop(loc,-1,Sniff::pcap_callback,NULL);
I think that what you should be gleaming from these compiler messages is that pointer to members are not the same as function pointers.
Whether making your member function static and thus converting its address from 'pointer to member' to 'pointer to function' will actually fix your problem is entirely dependent upon what your needs are.
You're passing a pointer to member function while the API expects a global function pointer. You've written that adding a static definition in the header has no effect, it should solve the problem since a static function isn't a member function (it's global). Could you share the reason it doesn't work when the function is static?
Commonly this can be done by using a ThreadFunction class. We will give it a non-virtual method "invoke" and a virtual method "run". Some variation of this will work:
class ThreadFunction
{
public:
virtual ~ThreadFunction();
void invoke( bool joinable );
protected: // or private
virtual void* run() = 0;
friend void * my_thread_func( void * );
GThread * gthread;
GError * error;
};
// In your cpp
void* my_thread_func( void * tf )
{
ThreadFunction * func = static_cast< ThreadFunction * >(tf);
return tf->run();
}
void ThreadFunction::invoke( bool joinable )
{
gthread = g_thread_create( my_thread_func, this, joinable, &error );
}
This is just an outline of the approach. You would create your thread to derive from ThreadFunction. (joinable may well be a feature of your implementation rather than a parameter passed in).
Here is what I'd like to do. I have a function pointer which wants a function like this:
void func(int a);
so I have a class:
class Foo {
public:
void func(int a);
};
Foo *foo = new Foo;
something->setFunction(foo->func);
or in my case:
testWidget[count] = new TestWidget;
testWidget[count]->eventMouseClick.addHandler(testWidget[0]->silly);
But this gives me:
Error 5 error C3867:
'TestWidget::silly': function call
missing argument list; use
'&TestWidget::silly' to create a
pointer to
member c:\users\josh\documents\visual
studio
2008\projects\agui\alleg_5\main.cpp 190
Is there a way I could make this work without using a static function?
Thanks
Is there a way I could make this work without using a static function?
No. You can't convert a pointer to member function to an ordinary function pointer.
If the callback accepted any callable object (or a std::function, for example), then you could bind the object to the member function and pass the result of that; unfortunately, you can't convert that result to an ordinary function pointer, though.
Your question is not very clear to me. But the error message from the compiler makes me feel that probably you want something like this something->setFunction(&foo->func);
An example might help in case of overloads
struct T{
void func(int){}
void func(double){}
};
void f(void (T::*f)(int)){}
void f(void (T::*f)(double)){}
int main(){
void (T::*fi)(int) = &T::func;
void (T::*fd)(double) = &T::func;
f(fi);
f(fd);
}