Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > passing a pointer to member function problem

Reply
Thread Tools

passing a pointer to member function problem

 
 
dice
Guest
Posts: n/a
 
      07-18-2006
Hi,
In order to use an external api call that requires a function pointer I
am currently creating static wrappers to call my objects functions.
I want to re-jig this so I only need 1 static wrapper function.
I would prefer to be able to pass the member function as a void* to the
static wrapper but I suspect this may not even be possible.
Another solution would be option 2 below but I can't figure out the
syntax to call obj->*pFn().

Thanks in advance for any suggestions / observations.

typedef void (*ExecFn)(void *);

void external_api_fn(ExecFn fn,void* p)
{
fn(p);
}

class Doit
{
public:
void fn1(void){printf("fn1\n");}
void fn2(void){printf("fn2\n");}
//current solution
static void static_wrapper1(void *obj)
{
((Doit*)obj)->fn1();
}
static void static_wrapper2(void *obj)
{
((Doit*)obj)->fn2();
}
//option 1
static void static_wrapper3(void *fn)
{
//fn();
}
//option 2
void (Doit::*pFn)(void);
static void static_wrapper4(void *obj)
{
//execute pFn - obj->*pFn - how to execute pFn for obj?
}
//--
Doit()
{
//what Im doing
external_api_fn(static_wrapper1,this);
external_api_fn(static_wrapper2,this);
//option 1 - cast fn1 to void?
//external_api_fn(static_wrapper3,fn1);
//external_api_fn(static_wrapper3,fn2);
//option 2
pFn = fn1;
external_api_fn(static_wrapper4,this);
pFn = fn2;
external_api_fn(static_wrapper4,this);
}
};

 
Reply With Quote
 
 
 
 
Stuart Redmann
Guest
Posts: n/a
 
      07-18-2006
dice wrote:
> Hi,
> In order to use an external api call that requires a function pointer I
> am currently creating static wrappers to call my objects functions.
> I want to re-jig this so I only need 1 static wrapper function.


The problem is that you need to pass the 'this' pointer to the function.

> I would prefer to be able to pass the member function as a void* to the
> static wrapper but I suspect this may not even be possible.


As a matter of fact, taking the address of a method is possible, but
wouldn't solve your problem, since you need to pass the 'this' pointer
as well (so you actually have to pass _two_ parameters to the function).

> Another solution would be option 2 below but I can't figure out the
> syntax to call obj->*pFn().


Of course. You don't have the 'this' pointer.

> typedef void (*ExecFn)(void *);
>
> void external_api_fn(ExecFn fn,void* p)
> {
> fn(p);
> }
>
> class Doit
> {
> public:
> void fn1(void){printf("fn1\n");}
> void fn2(void){printf("fn2\n");}
> //current solution
> static void static_wrapper1(void *obj)
> {
> ((Doit*)obj)->fn1();
> }
> static void static_wrapper2(void *obj)
> {
> ((Doit*)obj)->fn2();
> }
> //option 1
> static void static_wrapper3(void *fn)
> {
> //fn();
> }
> //option 2
> void (Doit::*pFn)(void);
> static void static_wrapper4(void *obj)
> {
> //execute pFn - obj->*pFn - how to execute pFn for obj?
> }
> //--
> Doit()
> {
> //what Im doing
> external_api_fn(static_wrapper1,this);
> external_api_fn(static_wrapper2,this);
> //option 1 - cast fn1 to void?
> //external_api_fn(static_wrapper3,fn1);
> //external_api_fn(static_wrapper3,fn2);
> //option 2
> pFn = fn1;
> external_api_fn(static_wrapper4,this);
> pFn = fn2;
> external_api_fn(static_wrapper4,this);
> }
> };
>


How about this:

#include <stdio.h>

typedef void (*ExecFn)(void);

void external_api_fn (ExecFn fn)
{
fn ();
}

class Doit
{
typedef void (Doit::*PtrToMemberForWrapperType) (void);
private:
static Doit* ms_ThisForWrapper;
static PtrToMemberForWrapperType ms_PtrMemberFuncForWrapper;

static void static_wrapper ()
{
// Invoke the member function of the static object.
(ms_ThisForWrapper->*ms_PtrMemberFuncForWrapper) ();
}

public:
void fn1(void) {printf("fn1\n");}
void fn2(void) {printf("fn2\n");}

void call_external_api_fn (PtrToMemberForWrapperType pMemberFunc)
{
// Store away the this pointer.
ms_ThisForWrapper = this;
ms_PtrMemberFuncForWrapper = pMemberFunc;
external_api_fn (&static_wrapper);
}
};

Doit:trToMemberForWrapperType Doit::ms_PtrMemberFuncForWrapper = 0;
Doit* Doit::ms_ThisForWrapper = 0;

int main ()
{
Doit MyDoit;
MyDoit.call_external_api_fn (Doit::fn1);

return 0;
}


I took the liberty to change the definition of ExecFn to a function that
takes no arguments, since your members fn1 and fn2 don't take arguments.
The above solution is not intended for use in multi-threaded
applications, since it uses static class members. If you want to use
this in a multi-threaded app, you have to introduce a map that stores
these pointers for each thread that uses the class.

Regards,
Stuart
 
Reply With Quote
 
 
 
 
dice
Guest
Posts: n/a
 
      07-18-2006

Stuart Redmann wrote:
> dice wrote:
> > Hi,
> > In order to use an external api call that requires a function pointer I
> > am currently creating static wrappers to call my objects functions.
> > I want to re-jig this so I only need 1 static wrapper function.

>
> The problem is that you need to pass the 'this' pointer to the function.
>
> > I would prefer to be able to pass the member function as a void* to the
> > static wrapper but I suspect this may not even be possible.

>
> As a matter of fact, taking the address of a method is possible, but
> wouldn't solve your problem, since you need to pass the 'this' pointer
> as well (so you actually have to pass _two_ parameters to the function).


yes - i wasn't quite thinking straight there, but see option 2 - this
is essentially the same thing, pass the 'this' pointer after setting a
function pointer in the object.

>
> > Another solution would be option 2 below but I can't figure out the
> > syntax to call obj->*pFn().

>
> Of course. You don't have the 'this' pointer.


'this' is passed as the second arg as per:
external_api_fn(static_wrapper4,this);

I thought that since the following is possible by passing 'this' as
void* obj:
((Doit*)obj)->fn1();
then static_wrapper4 could use something like the following:
(((Doit*)obj)->*pFn)();

>
> > typedef void (*ExecFn)(void *);
> >
> > void external_api_fn(ExecFn fn,void* p)
> > {
> > fn(p);
> > }
> >
> > class Doit
> > {
> > public:
> > void fn1(void){printf("fn1\n");}
> > void fn2(void){printf("fn2\n");}
> > //current solution
> > static void static_wrapper1(void *obj)
> > {
> > ((Doit*)obj)->fn1();
> > }
> > static void static_wrapper2(void *obj)
> > {
> > ((Doit*)obj)->fn2();
> > }
> > //option 1
> > static void static_wrapper3(void *fn)
> > {
> > //fn();
> > }
> > //option 2
> > void (Doit::*pFn)(void);
> > static void static_wrapper4(void *obj)
> > {
> > //execute pFn - obj->*pFn - how to execute pFn for obj?
> > }
> > //--
> > Doit()
> > {
> > //what Im doing
> > external_api_fn(static_wrapper1,this);
> > external_api_fn(static_wrapper2,this);
> > //option 1 - cast fn1 to void?
> > //external_api_fn(static_wrapper3,fn1);
> > //external_api_fn(static_wrapper3,fn2);
> > //option 2
> > pFn = fn1;
> > external_api_fn(static_wrapper4,this);
> > pFn = fn2;
> > external_api_fn(static_wrapper4,this);
> > }
> > };
> >

>
> How about this:
>
> #include <stdio.h>
>
> typedef void (*ExecFn)(void);
>
> void external_api_fn (ExecFn fn)
> {
> fn ();
> }
>
> class Doit
> {
> typedef void (Doit::*PtrToMemberForWrapperType) (void);
> private:
> static Doit* ms_ThisForWrapper;
> static PtrToMemberForWrapperType ms_PtrMemberFuncForWrapper;
>
> static void static_wrapper ()
> {
> // Invoke the member function of the static object.
> (ms_ThisForWrapper->*ms_PtrMemberFuncForWrapper) ();
> }
>
> public:
> void fn1(void) {printf("fn1\n");}
> void fn2(void) {printf("fn2\n");}
>
> void call_external_api_fn (PtrToMemberForWrapperType pMemberFunc)
> {
> // Store away the this pointer.
> ms_ThisForWrapper = this;
> ms_PtrMemberFuncForWrapper = pMemberFunc;
> external_api_fn (&static_wrapper);
> }
> };
>
> Doit:trToMemberForWrapperType Doit::ms_PtrMemberFuncForWrapper = 0;
> Doit* Doit::ms_ThisForWrapper = 0;
>
> int main ()
> {
> Doit MyDoit;
> MyDoit.call_external_api_fn (Doit::fn1);


this builds and works on my evC++ compiler, but not with mingw32-g++

>
> return 0;
> }
>
>
> I took the liberty to change the definition of ExecFn to a function that
> takes no arguments, since your members fn1 and fn2 don't take arguments.
> The above solution is not intended for use in multi-threaded
> applications, since it uses static class members. If you want to use


Multi threading is not a problem in this particular instance, but I was
trying to avoid static members for just this reason.

> this in a multi-threaded app, you have to introduce a map that stores
> these pointers for each thread that uses the class.
>
> Regards,
> Stuart


 
Reply With Quote
 
Stuart Redmann
Guest
Posts: n/a
 
      07-19-2006
dice wrote:

> Stuart Redmann wrote:
>
>>dice wrote:
>>
>>>Hi,
>>>In order to use an external api call that requires a function pointer I
>>>am currently creating static wrappers to call my objects functions.
>>>I want to re-jig this so I only need 1 static wrapper function.
>>>I would prefer to be able to pass the member function as a void* to the
>>>static wrapper but I suspect this may not even be possible.
>>>Another solution would be option 2 below but I can't figure out the
>>>syntax to call obj->*pFn().


I think I misunderstood you here. Invokation of member functions is
quite ugly (I had to look it up myself). If you have the object and the
pointer to the member function at hand, you can invoke it with the above
syntax, e.g. obj->*pFn (), but you have to enclose this in parentheses:
(obj->*pFn) ()

>>>typedef void (*ExecFn)(void *);
>>>
>>>void external_api_fn(ExecFn fn,void* p)
>>>{
>>> fn(p);
>>>}


A even much simpler solution comes into my mind: Since your API function
can be passed _any_ pointer, why don't we give it a pointer to a struct
containing both the object pointer and the member function pointer?
Something like this:

#include <stdio.h>

typedef void (*ExecFn)(void*);

void external_api_fn (ExecFn fn, void* p)
{
fn (p);
}

class Doit
{
typedef void (Doit::*PtrToMemberForWrapperType) (void);
struct SApiFunctionParameters
{
Doit* m_pThisPointer;
PtrToMemberForWrapperType m_pMemberFunction;
};

private:
static void static_wrapper (void* p_VoidPointer)
{
// Cast the passed pointer to a pointer to a parameter struct.
SApiFunctionParameters* pParameters = (SApiFunctionParameters*)
p_VoidPointer;

// Invoke the passed member function for the passed 'this' pointer.
(pParameters->m_pThisPointer->*pParameters->m_pMemberFunction) ();
}

public:
void fn1(void) {printf("fn1\n");}
void fn2(void) {printf("fn2\n");}

void call_external_api_fn (PtrToMemberForWrapperType pMemberFunc)
{
// Store away the 'this' AND the member function pointer.
SApiFunctionParameters ApiFunctionParameters;
ApiFunctionParameters.m_pThisPointer = this;
ApiFunctionParameters.m_pMemberFunction = pMemberFunc;
external_api_fn (&static_wrapper, &ApiFunctionParameters);
}
};

int main ()
{
Doit MyDoit;
MyDoit.call_external_api_fn (Doit::fn1);

return 0;
}

[snipped previous solution]
>
> this builds and works on my evC++ compiler, but not with mingw32-g++
>


(*blush*) I work with Visual C 6.0 (at least I have the courage to admit
it). Sorry, I can't help you there.

>
> Multi threading is not a problem in this particular instance, but I was
> trying to avoid static members for just this reason.
>


Luckily, multi-threading will be no problem when you use the struct version.

Regards,
Stuart
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Passing pointer to member function to different member function that then calls for_each pookiebearbottom@yahoo.com C++ 8 05-24-2005 01:50 PM
pointer to member function and pointer to constant member function Fraser Ross C++ 4 08-14-2004 06:00 PM
Passing a C++ object's member function to a C function expecing a function pointer! James Vanns C++ 7 01-21-2004 02:39 AM
Function pointer member variable to non-member function slide_o_mix C++ 0 10-15-2003 03:37 PM
Passing a pointer to member function as a parameter to another member function Newsgroup - Ann C++ 5 07-30-2003 02:54 AM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57