Calling C++ functions in C function through function pointers

D

D3|\\||\\|!$

Hi All!!

I have a C++ program that uses callback funtions which are the private
members of class. The code uses an API wrtiiten in C which supplies
callback-setting functions that require pointers to these functions...
The funtions wherein these API's callback-setting functions are
called, are public members of the same class of which the callbacks
are the private member.

Now the API functions are generating compile errors since they cannot
"understand" the C++ function pointers.





Consider the sample code:
class classname
{
public :

/* Constructor for the class */
classname ();

/* Destructor for the class */
~classname ();

/* Function calling API's callback setting function */
ReturnType1 Call_SetCallback (ReturnType2 arg1, ReturnType3
arg2,...);

private :

/* Callback to be passed through function pointer */
Callback (ReturnType4 arg1, ReturnType5 arg2,...);
};

ReturnType1 classname :: Call_SetCallback (ReturnType6 arg1,
ReturnType7 arg2,...)
{
/* PtrToCallback is a function pointer to Callback
(ReturnType4 arg1, ReturnType5 arg2,...)*/
SetCallback (&classname::Callback, void *arg);
}




OUTPUT on compilation:
error Error C2664: 'SetCallback' : cannot convert parameter 1 from
'ReturnType (__thiscall classname::* )(ReturnType4,ReturnType5)' to
'ReturnType1' FilePath\filename.cpp LineNumber




The same code had earlier been running perfectly fine as C code - I
simply moved the concerned functions to their specific places in the
aforesaid class and now its running into trouble.

Could somebody please suggest me a possible workaround..?? I cannot
export the concerned private callbacks outside the function or make
them public...

Warm Regards,
D3|\||\|!$
 
M

MisterE

somebody please suggest me a possible workaround..?? I cannot
export the concerned private callbacks outside the function or make
them public...

This is offtopic here, try comp.lang.c.and.cpp
 
W

Wolfgang Draxinger

D3|\||\|!$ said:
The same code had earlier been running perfectly fine as C code
- I simply moved the concerned functions to their specific
places in the aforesaid class and now its running into trouble.

Even though this is the C newsgroup, I'm now giving you a heads
up on C++: You CAN'T use class member functions for a C-style
callback.

Think about it: How would the callback function know, on which
instance of the class to operate? The proper way to do it is to
write a friend wrapper callback function, that takes a pointer
to the class instance as parameter and calls the member function
on that instance. If you want to keep it generic, let it take
two parameters: The instance and a pointer-to-member (this is
different from a ordinary C pointer, as this is more an offset,
than a absolute pointer) in form of void*, typecast those to the
proper types and call it.

class foo
{
int bar();
friend int foo_bar_wrapper(void * i_);
};

int foo_bar_wrapper(void * i_)
{
foo * instance = dynamic_cast<foo*> i_;
return instance->bar();
}

void register_callback(int(*p)(), void * data);

I'm too lazy, to give an example of the pointer-to-member method
here. Personally I actually discourage it's use, as it's prone
to introduce a lot of nasty to track down bugs.

Wolfgang Draxinger
 
D

Default User

MisterE said:
somebody please suggest me a possible workaround..?? I cannot

This is offtopic here, try comp.lang.c.and.cpp

There is no such newsgroup.




Brian
 
K

Keith Thompson

D3|\||\|!$ said:
I have a C++ program that uses callback funtions which are the private
members of class. The code uses an API wrtiiten in C which supplies
callback-setting functions that require pointers to these functions...
The funtions wherein these API's callback-setting functions are
called, are public members of the same class of which the callbacks
are the private member.

Now the API functions are generating compile errors since they cannot
"understand" the C++ function pointers.
[...]

As it happens, C++ provides mechanisms for calls between C and C++
programs; C does not. So your question is more suitable for
comp.lang.c++.

Ordinary C-to-C++ and C++-to-C function calls are covered in the C++
FAQ. Member functions are going to be trickier; consider a wrapper.
 
F

fred.l.kleinschmidt

Hi All!!

I have a C++ program that uses callback funtions which are the private
members of class. The code uses an API wrtiiten in C which supplies
callback-setting functions that require pointers to these functions...
The funtions wherein these API's callback-setting functions are
called, are public members of the same class of which the callbacks
are the private member.

Now the API functions are generating compile errors since they cannot
"understand" the C++ function pointers.

Consider the sample code:
class classname
{
    public :

        /* Constructor for the class */
        classname ();

        /* Destructor for the class */
        ~classname ();

       /* Function calling API's callback setting function */
       ReturnType1 Call_SetCallback (ReturnType2 arg1, ReturnType3
arg2,...);

    private :

        /* Callback to be passed through function pointer */
        Callback (ReturnType4 arg1, ReturnType5 arg2,...);

};

ReturnType1 classname :: Call_SetCallback (ReturnType6 arg1,
ReturnType7 arg2,...)
{
        /* PtrToCallback is a function pointer to Callback
(ReturnType4 arg1, ReturnType5 arg2,...)*/
        SetCallback (&classname::Callback, void *arg);

}

OUTPUT on compilation:
error Error C2664: 'SetCallback' : cannot convert parameter 1 from
'ReturnType (__thiscall classname::* )(ReturnType4,ReturnType5)' to
'ReturnType1'   FilePath\filename.cpp   LineNumber

The same code had earlier been running perfectly fine as C code - I
simply moved the concerned functions to their specific places in the
aforesaid class and now its running into trouble.

Could somebody please suggest me a possible workaround..?? I cannot
export the concerned private callbacks outside the function or make
them public...

Warm Regards,
D3|\||\|!$

This is a very common problem when using, for example, GUI toolkits
written in C. The easiest solution is to creeate a static function
in your class, where one of the parameters for that function is
the 'this' pointer.

An example using X/Motif:

In your C++ class header:
class MyClass {
public:
static void MyStaticFunction( Widget, XtPointer, XtPointer);
protected:
void MyRealFunction(...);
+

In your C++ code:
// Xt ships the 4th paramater as the clientData to
// callback functions
XtAddCallback( widget, XmNsomeCallback, MyStaticFunction, this );

Then, elsewhere in your C++ code, define the static function:

void MyStaticFunction( Widget w, XtPointer clientData, XtPointer
callData)
(
MyClass *me = (MyClass *)callData;
me->MyRealFunction(...)
)
 
I

Ian Collins

This is a very common problem when using, for example, GUI toolkits
written in C. The easiest solution is to creeate a static function
in your class, where one of the parameters for that function is
the 'this' pointer.

An example using X/Motif:

In your C++ class header:
class MyClass {
public:
static void MyStaticFunction( Widget, XtPointer, XtPointer);

While OT, this isn't strictly correct. The only type of function you
should pass to C from C++ is a function declared with extern "C"
linkage. Static member functions have C++ linkage, so use a friend instead.

A decent C++ compiler will issues a diagnostic if you pass anything else.
 
W

Wolfgang Draxinger

Ian said:
While OT, this isn't strictly correct. The only type of
function you should pass to C from C++ is a function declared
with extern "C"
linkage. Static member functions have C++ linkage, so use a
friend instead.

Could it be, that you mistake linkage for registering a callback,
which are completely different things?

extern "C" means nothing else, than to disable name mangling,
which is the only difference between C and C++ linkage. If you
know the mangled name of a C++ function you could as well
declare that for use with C. The whole idea behind extern "C" is
to disable it. It also means, that you can't overload functions
in a extern "C" block, as overloading is implemented through
name mangling.

As long no class instances are concerned the calling convention
for C++ functions is the same as for C. A static member function
is technically an ordinary function, with the additional twist,
that it lives in the class' namespace and thus has access to
protected and private members of any instance of that class.
Remember that C++ restricts access to class members at compile
time.

Wolfgang Draxinger
 
I

Ian Collins

Wolfgang said:
Could it be, that you mistake linkage for registering a callback,
which are completely different things?
No, I've been putting people straight on this for years over on c.l.c++.
extern "C" means nothing else, than to disable name mangling,
which is the only difference between C and C++ linkage.

There is nothing in either standard to say that. A C++ implementation
is free to use a different calling convention from C if it chooses to do
so. That's why the linkage specifier is there in the language.
As long no class instances are concerned the calling convention
for C++ functions is the same as for C.

As I said, it might be and typically is, but there is no guarantee.
 
G

Gerry Ford

Ian Collins said:
Wolfgang Draxinger wrote:
No, I've been putting people straight on this for years over on c.l.c++.


There is nothing in either standard to say that. A C++ implementation
is free to use a different calling convention from C if it chooses to do
so. That's why the linkage specifier is there in the language.

As I said, it might be and typically is, but there is no guarantee.

I think this question was multiposted to clc++, and through some strange
planetary alignment, I'm reading both forums now. There is no clc.and.cpp,
so don't waste your time like Brian and I did.

I think if OP does what Ian suggests, he'll get farther along in his
project.
 
D

Default User

Gerry Ford wrote:

I think this question was multiposted to clc++, and through some
strange planetary alignment, I'm reading both forums now. There is
no clc.and.cpp, so don't waste your time like Brian and I did.

Well, Brian didn't waste his time. He knew that there was no such
group. Had it been an alt group, then lookup would have been required.

There is alt.comp.lang.learn.c-c++, which might be what MisterE was
thinking of.



Brian
 
G

Gerry Ford

Default User said:
Gerry Ford wrote:



Well, Brian didn't waste his time. He knew that there was no such
group. Had it been an alt group, then lookup would have been required.
So what requires looking this up? (The dangers of passive voice, or is it
mood?) :)
 
W

Wolfgang Draxinger

Ian said:
No, I've been putting people straight on this for years over on
c.l.c++.


There is nothing in either standard to say that. A C++
implementation is free to use a different calling convention
from C if it chooses to do
so. That's why the linkage specifier is there in the language.

Umm, I don't see any reason, why linkage should be in any way
related to calling convention. The OP asked about callbacks,
which means: The address of a function (actually the point in
memory, where the function's code begins) is stored, so that it
can be called if something funny happens. Calling convention
OTOH describes, what preparations must be done, before
instructing the CPU to enter that function. And let's face it:
In C the calling convention is not supplied by the address-of
operator of the function, but by the pointer the address is
stored in. It's perfectly possible to pass a pascall-calling
convention function pointer for callback, but as soon the
callback is entered, the program will crash. A good compiler
will (hopefully) emit a warning about type mismatch.

Yes at the very low level this is related to linkage, but don't
lets get to academic on this topic. The fact is, that all C++
implementations (compilers) share their condebase with a plain C
compiler and thus will share the C calling convention.
Practically this reduces 'extern "C"' to a name mangling
disabler, and in some textbooks on C++ it's actually described
(wrongly from the academic, but correct from the practical point
of view) as such.
As I said, it might be and typically is, but there is no
guarantee.

No there isn't of course. This is IMHO a big drawback on C++ --
that it has no ABI standard I mean. I'm not aware of any
implementation, that has a calling convention for C++ different
from C. Of course, if you can name me one (and I mean a
implementation of C++ that's in widespread use, i.e. more than
10 users) then that's a different story.

This is the main reason, that I turned my back on C++. The lack
of a real ABI standard makes it impossible to have sane ways to
implement binary module systems. Everything is alright, as long
the compilers agree on how to do things, but if not... Don't get
me started on this. For the same reason I also don't use Qt
anymore, but switched to GTK+.

Wolfgang Draxinger
 
G

Gerry Ford

Wolfgang Draxinger said:
Ian said:
Wolfgang Draxinger wrote:
[...]
There is nothing in either standard to say that. A C++
implementation is free to use a different calling convention
from C if it chooses to do
so. That's why the linkage specifier is there in the language.

Umm, I don't see any reason, why linkage should be in any way
As I said, it might be and typically is, but there is no
guarantee.

No there isn't of course. This is IMHO a big drawback on C++ --
snip

When C sharp appeared, I conjectured the future existence of c flat.

Maybe C++-- might be good shorthand that includes c, c plusplus, and the
most recent MS flavor.
 
I

Ian Collins

Wolfgang said:
Ian Collins wrote:



No there isn't of course. This is IMHO a big drawback on C++ --

The potential difference in calling convention is between C and C++.
The two are unique languages, they may use different calling conventions
on the same platform. C++ provides extern "C" as a means of generating
functions usable by C (and by extension, other C++ compilers on that
platform).
 
K

Keith Thompson

Default User said:
No idea what this is supposed to mean.

I suggest that it's time to sit back in silence and wait for "Gerry
Ford" to start making sense. If he never does, so be it.
 
D

Default User

Keith said:
I suggest that it's time to sit back in silence and wait for "Gerry
Ford" to start making sense. If he never does, so be it.

Yeah, I'd already replied before I read some of his other . . .
"unique" contributions.




Brian
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,997
Messages
2,570,241
Members
46,831
Latest member
RusselWill

Latest Threads

Top