Pointer to member function

I want to implement a C++ wrapper to C code that requires a function
pointer to be passed in. Specifically, I want a wrapper for pthread that
clients can use as a base class.

Is there a way of passing a non-static member function in that will do
this?

In the following code, if I use the static k_main then it builds and
runs, but the derived class uses the implementation in CMyThread.

If I use a virtual member function, I get a compile error:
thread2.cpp:21: error: argument of type ‘void* (CMyThread:(void*)’
does not match ‘void* (*)(void*)’

Presumably this is because the member function pointer still expect the
this parameter when it is called.

I have thought of an alternative way that requires the CMyThread
constructor to pass the this pointer as an additional argument that is
then used in k_main to call the member function. It just looks really
horrible.

Advertisements

On Jun 26, 3:12 pm, Dan Smithers <> wrote:
> I want to implement a C++ wrapper to C code that requires a function
> pointer to be passed in. Specifically, I want a wrapper for pthread that
> clients can use as a base class.
>
> Is there a way of passing a non-static member function in that will do
> this?
>

Advertisements

On Jun 26, 12:17 pm, tragomaskhalos <>
wrote:
> On Jun 26, 3:12 pm, Dan Smithers <> wrote:
>
> > I want to implement a C++ wrapper to C code that requires a function
> > pointer to be passed in. Specifically, I want a wrapper for pthread that
> > clients can use as a base class.
>
> > Is there a way of passing a non-static member function in that will do
> > this?
>
> Seehttp://www.parashift.com/c++-faq-lite/pointers-to-members.html

kamit wrote:
> Check out boost::thread.
>
> On Jun 26, 12:17 pm, tragomaskhalos <>
> wrote:
>> On Jun 26, 3:12 pm, Dan Smithers <> wrote:
>>
>>> I want to implement a C++ wrapper to C code that requires a function
>>> pointer to be passed in. Specifically, I want a wrapper for pthread that
>>> clients can use as a base class.
>>> Is there a way of passing a non-static member function in that will do
>>> this?
>> Seehttp://www.parashift.com/c++-faq-lite/pointers-to-members.html
>

Thanks, I've bookmarked the FAQ now (until Firefox eats the list).
I've done it by passing a this to a static wrapper.#

On Jun 26, 4:12 pm, Dan Smithers <> wrote:
> I want to implement a C++ wrapper to C code that requires a
> function pointer to be passed in. Specifically, I want a
> wrapper for pthread that clients can use as a base class.
> Is there a way of passing a non-static member function in that
> will do this?

No. There's not even a way of passing a static member function.

First, of course, the calling conventions, and even the calling
syntax, of a non-static member function is necessarily different
from that of a static member or a free function; when calling a
non-static member, the compiler must associate an object with
the call. Obviously, there's no way that a C function can do
this. But there's also no guarantee that C and C++ use the same
calling conventions (and I've used compilers where they didn't).
And since the ``extern "C"'' function is going to call the
function whose address you pass it using the C calling
conventions, you can only pass it a pointer to a function which
uses the C calling conventions: a function declared ``extern
"C"'' in C.

In the case of functions like pthread_create, which also take a
void*, be very careful about your conversions to and from void*
as well. Once you've got the void*, the only thing you can do
with it is cast it back to the exact type which was converted to
get it. In particular, if you call pthread_create with a
Derived* as the last argument, then in the start up function,
you must cast it back to Derived*; casting it to Base* results
in undefined behavior.
> In the following code, if I use the static k_main then it
> builds and runs, but the derived class uses the implementation
> in CMyThread.
> If I use a virtual member function, I get a compile error:
> thread2.cpp:21: error: argument of type ?void*
> (CMyThread:(void*)? does not match ?void* (*)(void*)?
> Presumably this is because the member function pointer still
> expect the this parameter when it is called.

Member function pointers typically have a completely different
layout from non-member function pointers, precisely because they
must be able to handle virtual functions. (If you take the
address of a virtual &Base::f, and call it through a Derived* p,
(p->*f)(), or through a Base* which actually points to a
Derived, it is Derived::f() which will be called.)
> I have thought of an alternative way that requires the
> CMyThread constructor to pass the this pointer as an
> additional argument that is then used in k_main to call the
> member function. It just looks really horrible.

It's the standard procedure. It is, in fact, the exact reason
why the void* is there in pthread_create (and most other
functions of its ilk). Calling a member function requires a
user supplied object. The purpose of the void* is to allow the
user to pass a pointer to an "object" (which, of course, can be
anything the user wants; boost::thread passes the address of a
Boost functional object, for example, and in some very special
cases, I've used it to pass a small integer, with some pretty
hairy reinterpret_casting).
> #include <stdio.h>
> #include <stdlib.h>
> #include <pthread.h>
> class CMyThread

And since you're dealing with an object, you don't need the
additional args---they can just be member variables of the
object.

Finally, of course, you can't call pthread_create from a
constructor of a base class without encuring race conditions; as
a general rule, you should never call it from the constructor of
a "thread" object which you expect run.
> }
> CMyThread::~CMyThread()
> {
> pthread_join( m_thread, NULL);

pthread_join can block. I'm not sure its a good idea to call it
from a destructor. (Destructors are called during stack
walkback, in case of an exception. Which is generally a context
where you don't want to block for an indefinite time.)
> }

The usual solution for this sort of thing is to separate the
thread from what it does. Not only does it work, but it's a lot
cleaner in the long run. Thus, you might end up with something
like:

As it worked, I hadn't really considered the difficulties that other
compilers might cause.
> And since you're dealing with an object, you don't need the
> additional args---they can just be member variables of the
> object.
>
> Finally, of course, you can't call pthread_create from a
> constructor of a base class without encuring race conditions; as
> a general rule, you should never call it from the constructor of
> a "thread" object which you expect run.
>
>> }
>
>> CMyThread::~CMyThread()
>> {
>> pthread_join( m_thread, NULL);
>
> pthread_join can block. I'm not sure its a good idea to call it
> from a destructor. (Destructors are called during stack
> walkback, in case of an exception. Which is generally a context
> where you don't want to block for an indefinite time.)

I'll have to think of a way of tidying up if exceptions are thrown.
>> }
>
> The usual solution for this sort of thing is to separate the
> thread from what it does. Not only does it work, but it's a lot
> cleaner in the long run. Thus, you might end up with something
> like:

I had come up with something similar, but in reverse.

I had a virtual class Thread that the user derives from, which contained
an implementation class ThreadImp that is created when the thread is
started.

I was still passing around void* arg lists without stopping to think
about whether I really needed to. (In the latest version I stored a void
* arg in the Thread class.

[...]
> >> CMyThread::~CMyThread()
> >> {
> >> pthread_join( m_thread, NULL);
> > pthread_join can block. I'm not sure its a good idea to
> > call it from a destructor. (Destructors are called during
> > stack walkback, in case of an exception. Which is generally
> > a context where you don't want to block for an indefinite
> > time.)
> I'll have to think of a way of tidying up if exceptions are
> thrown.

It is a problem. And I don't know of a good solution.
(Boost detaches the thread, which is even worse than doing the
join.) What you want to do is to force the other thread to
terminate as rapidly as possible, and then join. But at least
at present, pthread_cancel doesn't work (portably) in C++, and
even if it did, it's largely advisory, at least in some of it's
aspects.
> >> }

Share This Page

Welcome to The Coding Forums!

Welcome to the Coding Forums, the place to chat about anything related to programming and coding languages.

Please join our friendly community by clicking the button below - it only takes a few seconds and is totally free. You'll be able to ask questions about coding or chat with the community and help others.
Sign up now!