C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Using static member functions as C callbacks
Goto page 1, 2  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
John Dumais
Guest





PostPosted: Wed Dec 08, 2004 11:27 pm    Post subject: Using static member functions as C callbacks Reply with quote



Hello,

I'm using a commercial C library that parses particular kinds of files by
running callback functions defined in client code. The header file declares
a pointer to
function type using syntax similar to...

extern "C"{
typedef void (*Handler)(void*, const char*, const char**);
}

You connect a callback function to this C library by registering a function
pointer. I wanted to use a class in my C++ code as the callback function,
so I declared
a class like this...

class ParticularKindOfHandler{
public:
// declaration for handler function
static void MyHandler(void *v1, const char *v2, const char **v3);

// accessor to return pointer to callback function
virtual Handler GetHandler() { return MyHandler; }
};

The GetHandler function causes one compiler to emit a warning something
like...

Anachronism: Using void(*)(void*, const char*, const char**) to initialize
extern "C" void(*)(void*, const char*, const char**)

So it would seem that using a static member function to implement the C
callback is not a good idea. Can anyone explain why?
Also, what's a better alternative?

If you would like to respond directly through email, remove the nospam_
prefix to my email address.

Thanks,



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Daniel Krügler (ne Spange
Guest





PostPosted: Thu Dec 09, 2004 9:18 am    Post subject: Re: Using static member functions as C callbacks Reply with quote



Hello John Dumais,

John Dumais schrieb:

Quote:
I'm using a commercial C library that parses particular kinds of files by
running callback functions defined in client code. The header file declares
a pointer to
function type using syntax similar to...

extern "C"{
typedef void (*Handler)(void*, const char*, const char**);
}


[snip]


Quote:
I wanted to use a class in my C++ code as the callback function,
so I declared
a class like this...

class ParticularKindOfHandler{
public:
// declaration for handler function
static void MyHandler(void *v1, const char *v2, const char **v3);

// accessor to return pointer to callback function
virtual Handler GetHandler() { return MyHandler; }
};

The GetHandler function causes one compiler to emit a warning something
like...

Anachronism: Using void(*)(void*, const char*, const char**) to initialize
extern "C" void(*)(void*, const char*, const char**)

So it would seem that using a static member function to implement the C
callback is not a good idea. Can anyone explain why?
Also, what's a better alternative?

The compiler is right, because due to the different linkage declarations

we (can have) two different
types here. The linkage of ParticularKindOfHandler::MyHandler ist extern
"C++" and it is implementation defined
whether this type is compatible to extern "C" linkage. Regrettably it is
not possible to declare a static
function member with different linkage although this is an artifical
restriction which should be fixed IMHO.

As a workaround I use a friend declared external function of wanted
linkage (with the disadvantage, that
this function can be called by everyone). Of course the friend
declaration is not always necessary (e.g.
from your example it is not possible to deduce whether it needs acces to
its wrapping class of not, but
I strongly assume that your implementation of
ParticularKindOfHandle::MyHandler needs private access) :

namespace Internal {

// declaration for handler function
extern "C" void MyPrivatePersonalHandler(void *v1, const char *v2, const char **v3);

}

class ParticularKindOfHandler{
public:
friend void ::Internal::MyPrivatePersonalHandler(void *v1, const char *v2, const char **v3);

// accessor to return pointer to callback function
virtual Handler GetHandler() { return MyHandler; }
};

Greetings from Bremen,

Daniel Krügler







[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Branimir Maksimovic
Guest





PostPosted: Thu Dec 09, 2004 9:19 am    Post subject: Re: Using static member functions as C callbacks Reply with quote



John Dumais wrote:
Quote:
Hello,

I'm using a commercial C library that parses particular kinds of
files by
running callback functions defined in client code. The header file
declares
a pointer to
function type using syntax similar to...

extern "C"{
typedef void (*Handler)(void*, const char*, const char**);
}

You connect a callback function to this C library by registering a
function
pointer. I wanted to use a class in my C++ code as the callback
function,
so I declared
a class like this...

class ParticularKindOfHandler{
public:
// declaration for handler function
static void MyHandler(void *v1, const char *v2, const char
**v3);

// accessor to return pointer to callback function
virtual Handler GetHandler() { return MyHandler; }
};

The GetHandler function causes one compiler to emit a warning
something
like...


Well, if calling conventions of linkage specification does not match
you are in trouble. Problem is that c++ compiler is not obliged
to use same calling convention as c compiler.
If you wan't to compile such code with compilers that you don't know
linkage specification I wouldn't advise this approach.
This is a pain when trying to interface with c as even namespaces
cannot be used to differ function names:
eg
namespace One{
extern "C" void h(){}
}

namespace Two{
extern "C" void h(){}
}

This is ill formed as h has two definitions.
There is other solution for this problem. Usually all callback
functions uses void* to get some opaque data from user
so you can pass pointer to your object;
extern "C" void callback(void* p, const char* p1, const char**p2)
{
static_cast<Object*>(p)->handler(p1,p2); // in this case function
// does not have to be static at all
}
//
//.....
register_callback(&callback, new ConcreteObject);
//.......

If there is no such opaque data to be registered
with callback function, you are in trouble.
But first parameter of your callback is void* so I can smell
similar mechanism Smile
Even if void* parameter is not provided by caller of register_callback
,there must be way to provide mappings between parameter and
object so you can lookup into some table of your callbacks
to find appropriate object.

Greetings, Bane.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
James Rafter
Guest





PostPosted: Thu Dec 09, 2004 9:22 am    Post subject: Re: Using static member functions as C callbacks Reply with quote

Quote:
So it would seem that using a static member function to implement the
C
callback is not a good idea. Can anyone explain why?
Also, what's a better alternative?

C++ mangles function names, C does not. The extern C declaration turns

off name mangling so C++ can work with C.

Declare your callbacks functions outside of any class and declare them
extern C. You can hide these implementation details from users of
your class by having your .cpp file depend on them but not having your
..h file (explicitly) depend on them. That is, you can call these
functions by calling them from within your C++ functions. I'm sure
there are other ways also.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
L.Suresh
Guest





PostPosted: Thu Dec 09, 2004 9:22 am    Post subject: Re: Using static member functions as C callbacks Reply with quote

The address of a static function in the class is an ordinary function
pointer. You can pass it to
C libraries. I guess you are getting stuck with the linkage.

--lsu


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Victor Bazarov
Guest





PostPosted: Thu Dec 09, 2004 9:31 am    Post subject: Re: Using static member functions as C callbacks Reply with quote

John Dumais wrote:
Quote:
I'm using a commercial C library that parses particular kinds of files by
running callback functions defined in client code. The header file declares
a pointer to
function type using syntax similar to...

extern "C"{
typedef void (*Handler)(void*, const char*, const char**);
}

You connect a callback function to this C library by registering a function
pointer. I wanted to use a class in my C++ code as the callback function,
so I declared
a class like this...

class ParticularKindOfHandler{
public:
// declaration for handler function
static void MyHandler(void *v1, const char *v2, const char **v3);

// accessor to return pointer to callback function
virtual Handler GetHandler() { return MyHandler; }
};

The GetHandler function causes one compiler to emit a warning something
like...

Anachronism: Using void(*)(void*, const char*, const char**) to initialize
extern "C" void(*)(void*, const char*, const char**)

So it would seem that using a static member function to implement the C
callback is not a good idea. Can anyone explain why?

I think it is related to the fact that class members have C++ linkage, and
not "C" linkage.

Quote:
Also, what's a better alternative?

Another function that you explicitly declare 'extern "C"' which just
forwards the call to the member function (if you're so inclined to have
the actual processing in the member).

V

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Stephan Brönnimann
Guest





PostPosted: Fri Dec 10, 2004 1:46 am    Post subject: Re: Using static member functions as C callbacks Reply with quote


John Dumais wrote:
Quote:
Hello,

I'm using a commercial C library that parses particular kinds of
files by
running callback functions defined in client code. The header file
declares
a pointer to
function type using syntax similar to...

extern "C"{
typedef void (*Handler)(void*, const char*, const char**);
}

You connect a callback function to this C library by registering a
function
pointer. I wanted to use a class in my C++ code as the callback
function,
so I declared
a class like this...

class ParticularKindOfHandler{
public:
// declaration for handler function
static void MyHandler(void *v1, const char *v2, const char
**v3);

// accessor to return pointer to callback function
virtual Handler GetHandler() { return MyHandler; }
};

The GetHandler function causes one compiler to emit a warning
something
like...

Anachronism: Using void(*)(void*, const char*, const char**) to
initialize
extern "C" void(*)(void*, const char*, const char**)

So it would seem that using a static member function to implement the
C
callback is not a good idea. Can anyone explain why?
Also, what's a better alternative?

If you would like to respond directly through email, remove the
nospam_
prefix to my email address.

Thanks,



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

John

AFAICS using static member functions is actually the
only way how you can implement such callbacks. Your
compiler however issues a very clever message:

Quote:
From ParticularKindOfHandler::GetHandler() how are
going to access the this pointer of a particular

instance of ParticularKindOfHandler for which the
member was called? Compare with the code that I'm using
to start a POSIX thread (sorry for the missing indentation:
Google beta messes it up)

#include <pthread.h>

extern "C" void* callThreadFunction(void* threadBase);

class ThreadBase {
public:
virtual void threadFunction() = 0;
void start();
// other stuff snipped
protected:
pthread_t thread_;
};

void ThreadBase::start()
{
pthread_create(&thread_, 0, callThreadFunction, this);
// ^
// note the this pointer which is passed as argument
// to callThreadFunction().
}

void* callThreadFunction(void* this_)
{
ThreadBase* thread = static_cast<ThreadBase*>(this_);
thread->threadFunction();
return 0;
}

Regards,
Stephan Brönnimann
[email]broeni (AT) osb-systems (DOT) com[/email]
http://www.osb-systems.com
Open source rating and billing engine for
communication networks.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Francis Glassborow
Guest





PostPosted: Fri Dec 10, 2004 1:52 am    Post subject: Re: Using static member functions as C callbacks Reply with quote

In article <1102568722.325191.55350 (AT) z14g2000cwz (DOT) googlegroups.com>, James
Rafter <jjr2004a (AT) yahoo (DOT) com> writes
Quote:
So it would seem that using a static member function to implement the
C
callback is not a good idea. Can anyone explain why?
Also, what's a better alternative?

C++ mangles function names, C does not. The extern C declaration turns
off name mangling so C++ can work with C.

Declare your callbacks functions outside of any class and declare them
extern C. You can hide these implementation details from users of
your class by having your .cpp file depend on them but not having your
.h file (explicitly) depend on them. That is, you can call these
functions by calling them from within your C++ functions. I'm sure
there are other ways also.

Yes.

1)


struct X {
static void foo(int);
// other
};

extern "C" {
inline void foo(int i){return X::foo(i);}
}

Will work, and work efficiently on almost all compilers.

2)
IIRC correctly the following syntax also works:

extern "C" {
typedef void (f_c)(int);
}

struct X{
static f_c foo;
// other
};

also works.

I would prefer not to use a friend declaration for this problem.


--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Pete Becker
Guest





PostPosted: Fri Dec 10, 2004 2:08 am    Post subject: Re: Using static member functions as C callbacks Reply with quote

James Rafter wrote:
Quote:
C++ mangles function names, C does not.

Most C compilers mangle names by prepending an underscore.

Quote:
The extern C declaration turns
off name mangling so C++ can work with C.


That's the least important part of what it does. It tells the compiler
to generate the code so that it's compatible with C. That can affect the
calling convention and a bunch of other things. Name mangling typically
prevents linking code to places where it shouldn't be linked.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Daniel Krügler (ne Spange
Guest





PostPosted: Fri Dec 10, 2004 11:00 am    Post subject: Re: Using static member functions as C callbacks Reply with quote

Hello Francis Glassborow,

Francis Glassborow schrieb:

Quote:
IIRC correctly the following syntax also works:

extern "C" {
typedef void (f_c)(int);
}

struct X{
static f_c foo;
// other
};

also works.

I would prefer not to use a friend declaration for this problem.


That is a very nice solution and is far better than my workaround! This
also makes
my claims invalid that current C++ does not make it possible to declare
a static
member of user-defined linkage - Sorry.

Thanks,

Daniel


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Francis Glassborow
Guest





PostPosted: Fri Dec 10, 2004 12:29 pm    Post subject: Re: Using static member functions as C callbacks Reply with quote

In article <g-OdnXMn9uFC-SXcRVn-rQ (AT) rcn (DOT) net>, Pete Becker
<petebecker (AT) acm (DOT) org> writes
Quote:
That's the least important part of what it does. It tells the compiler
to generate the code so that it's compatible with C. That can affect the
calling convention and a bunch of other things. Name mangling typically
prevents linking code to places where it shouldn't be linked.

Actually I think you meant 'compatible with the calling conventions of a
companion C compiler if there is one.'

There is no requirement that there be such a C compiler, and the
calling/linkage conventions can, and do, vary between C implementations.


--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Francis Glassborow
Guest





PostPosted: Fri Dec 10, 2004 3:53 pm    Post subject: Re: Using static member functions as C callbacks Reply with quote

In article <41b96354$0$6941$4d4ebb8e (AT) businessnews (DOT) de.uu.net>, "Daniel
Krügler (ne Spangenberg)" <dsp (AT) bdal (DOT) de> writes
Quote:
Hello Francis Glassborow,

Francis Glassborow schrieb:

IIRC correctly the following syntax also works:

extern "C" {
typedef void (f_c)(int);
}

struct X{
static f_c foo;
// other
};

also works.

I would prefer not to use a friend declaration for this problem.


That is a very nice solution and is far better than my workaround! This
also makes
my claims invalid that current C++ does not make it possible to declare
a static
member of user-defined linkage - Sorry.


No need to apologise, too few people know how typedefs can be used to
solve this problem and allied ones. I have an advantage because I was
part of the small group who made linkage specification part of the type
of a function. Whilst we were convinced it was the right thing to do
(because there really were compilers where the C and C++ calling
conventions were different) we had to address issues such as the use of
static members as callbacks.

This is one of the places where typedef isn't just a shorthand but
supports something that can be done in no other way.


--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Pete Becker
Guest





PostPosted: Fri Dec 10, 2004 5:01 pm    Post subject: Re: Using static member functions as C callbacks Reply with quote

Francis Glassborow wrote:
Quote:
In article <g-OdnXMn9uFC-SXcRVn-rQ (AT) rcn (DOT) net>, Pete Becker
[email]petebecker (AT) acm (DOT) org[/email]> writes

That's the least important part of what it does. It tells the compiler
to generate the code so that it's compatible with C. That can affect the
calling convention and a bunch of other things. Name mangling typically
prevents linking code to places where it shouldn't be linked.


Actually I think you meant 'compatible with the calling conventions of a
companion C compiler if there is one.'

I meant what I said. If you would have said something different by all
means say it. In my view, excessive detail is just as bad as
insufficient detail. When someone's lost in the woods it doesn't help
them to describe what insects they're seeing in the bark on the trees.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Branimir Maksimovic
Guest





PostPosted: Sat Dec 11, 2004 3:57 am    Post subject: Re: Using static member functions as C callbacks Reply with quote

Francis Glassborow wrote:
Quote:
In article <1102568722.325191.55350 (AT) z14g2000cwz (DOT) googlegroups.com>,
James
Rafter <jjr2004a (AT) yahoo (DOT) com> writes
So it would seem that using a static member function to implement
the
C
callback is not a good idea. Can anyone explain why?
Also, what's a better alternative?

C++ mangles function names, C does not. The extern C declaration
turns
off name mangling so C++ can work with C.

Declare your callbacks functions outside of any class and declare
them
extern C. You can hide these implementation details from users of
your class by having your .cpp file depend on them but not having
your
.h file (explicitly) depend on them. That is, you can call these
functions by calling them from within your C++ functions. I'm sure
there are other ways also.

Yes.

1)


struct X {
static void foo(int);
// other
};

extern "C" {
inline void foo(int i){return X::foo(i);}
}

Will work, and work efficiently on almost all compilers.

2)
IIRC correctly the following syntax also works:

extern "C" {
typedef void (f_c)(int);
}

struct X{
static f_c foo;
// other
};

also works.

I would prefer not to use a friend declaration for this problem.


when I saw that following compiles I've dropped from my chair :0)
extern "C"{
typedef void func_t(void*);
typedef void func1_t(char*);
}

struct Test{
static func_t func;
static func1_t func;
};

extern "C"
void Test::func(void*)
{
}

extern "C"
void Test::func(char*)
{
}

int main()
{
Test::func((void*)0);
}

Heh, this news group is very, very usefull.
This solves A LOT of c<->c++ interfacing pains Smile
Thak you.

Greetings, Bane.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
=3D?ISO-8859-1?Q?Falk_Tan
Guest





PostPosted: Sun Dec 12, 2004 12:04 am    Post subject: Re: Using static member functions as C callbacks Reply with quote

Branimir Maksimovic wrote:

Quote:
when I saw that following compiles I've dropped from my chair :0)
extern "C"{
typedef void func_t(void*);
typedef void func1_t(char*);
}

struct Test{
static func_t func;
static func1_t func;
};

As stated in =A7 7.5/4 "A C language linkage is ignored for the names of
class members and the member function type of class member functions."
and the 2 examples that follow, both functions will have C++ linkage.


A different problem is with templates:
________________________________________________________
#include <pthread.h> // Just for example, not part of C++ Standard
#include <cassert>

extern "C" { typedef void* pthread_entry_func(void*); }

template<typename T, void* (T::*memfun)()>
pthread_entry_func entry_routine; // declaration

template<typename T, void* (T::*memfun)()>
void* entry_routine(void* arg) // definition
{
return (static_cast<T*>(arg)->*memfun)();
}

/////////////////////////////////////////////////////////

class foo
{
pthread_t my_thread_id;
// ...
void* bar() { /* ... */ }

public:
foo(/* ... */)
{
int result = pthread_create(&my_thread_id, 0,
entry_routine<foo, &foo::bar>, // must be=
'extern "C"'!
this);
assert(result == 0);
}

~foo()
{
void* status = 0;
int result = pthread_join(my_thread_id, &status);
assert(result == 0);
}
}; // class foo
________________________________________________________

Unless I overlooked something, the Standard is silent on
the linkage specification of functions that are instantiated
from function templates, so it is not clear to me if the above
code is well-formed or not (provided the implementation knows
about pthreads, of course).

Comeau's on-line compiler (which correctly rejects assignments
between 'extern "C++" and 'extern "C"' function pointers) permits
assigning of pointers to templated functions declared as above to
'extern "C"' function pointers.

Falk

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.