Setting a C++ function as callback to a C Function!

J

Jay

Hi All,

I have a C interface which takes a C function pointer as input for
setting callback. Now, I want to set a C++ function for the same.

I am getting a calling convention error.

Is it possible for me to do this?

Any pointers in that direction would be of great help.

Thanks in Advance!

Regards,
Jayaraghavendran.K
 
P

peter koch

Hi All,

I have a C interface which takes a C function pointer as input for
setting callback. Now, I want to set a C++ function for the same.

I am getting a calling convention error.

Is it possible for me to do this?

Any pointers in that direction would be of great help.

It is simple: If a C-function is expected, a C++ function probably
will not work, so your approach will not work: you must use a C-
function.
Luckily, creating a C-function is easy: just use extern "C" - you may
look it up if you don't know how.

/Peter
 
I

Ian Collins

Sam said:
Technically, this is allowed only if you declare your functio with C
linkage, inside an extern "C" {} block. However, in practice, you can
get away with using any static function.

For some definitions of "get away with".
 
J

Juha Nieminen

Sam said:
You cannot register a class
member function as a callback from C code.

But you can get around it if, like many C libraries using callbacks,
the callback mechanism takes a user-defined data pointer. You can do
something like this (semi-pseudocode):

class MyClass
{
public:
returnType callbackFunction(paramType param);
};

extern "C"
{
// Function of the form required by the C library. For example:
returnType callbackFunction(paramType param, void* userData)
{
MyClass* instance = (MyClass*)userData;
return instance->callbackFunction(param);
}
}

namespace
{
MyClass myClassInstance;
}

void someFunctionSomewhere()
{
// Let's assume the C library function for setting the callback
// function has the form:
// void cLibSetCallbackFunc(returnType(*)(paramType, void*),
// void* userData);

cLibSetCallbackFunc(callbackFunction, &myClassInstance);
}
 
Z

Zachary Turner

  But you can get around it if, like many C libraries using callbacks,
the callback mechanism takes a user-defined data pointer. You can do
something like this (semi-pseudocode):

class MyClass
{
 public:
    returnType callbackFunction(paramType param);

};

extern "C"
{
    // Function of the form required by the C library. For example:
    returnType callbackFunction(paramType param, void* userData)
    {
        MyClass* instance = (MyClass*)userData;
        return instance->callbackFunction(param);
    }

}

namespace
{
    MyClass myClassInstance;

}

void someFunctionSomewhere()
{
    // Let's assume the C library function for setting the callback
    // function has the form:
    // void cLibSetCallbackFunc(returnType(*)(paramType, void*),
    //                          void* userData);

    cLibSetCallbackFunc(callbackFunction, &myClassInstance);

}

I'm guessing that in his case the signature of the callback function
does not include a void*.

The best way is to do the following:

//Top of cpp file that contains the place you are calling the C-
interface

//make sure this is in an anonymous namespace. You do NOT want any
other code accessing this
namespace
{
static ClassWithCallbackFunction* gCallbackInstance = NULL;
extern "C" void callbackWrapper(int callbackArg)
{
gCallbackInstance->CallbackFunc(callbackArg);
}
}

int main(int argc, char** argv)
{
gCallbackInstance = new ClassWithCallbackFunction();
c_func_that_requires_callback(callbackWrapper);
}


This is obviously bad for a lot of reasons, but if it's really the
only way for you to interface with a pre-existing library for which
there is no way to modify the code, then there aren't a whole lot of
options
 
Y

yeolahim

Hi All,

I have a C interface which takes a C function pointer as input for
setting callback. Now, I want to set a C++ function for the same.

I am getting a calling convention error.

Is it possible for me to do this?

Any pointers in that direction would be of great help.

Thanks in Advance!

Regards,
Jayaraghavendran.K

What are you doing ?
Can you show code ?
because:
c++ function as callback doesn't differ from c function as callback.
 
J

James Kanze

Jay writes:
Technically, this is allowed only if you declare your functio
with C linkage, inside an extern "C" {} block. However, in
practice, you can get away with using any static function.

Not if you use a good compiler. VC++ and g++ let you get away
with it, but the standard requires a diagnostic, and good C++
compilers issue one.
You cannot register a class member function as a callback from
C code.

Because, of course, they can't be ``extern "C"''. Both VC++ and
g++ do allow static class members, as well.
 
J

James Kanze

What are you doing ?
Can you show code ?
because:
c++ function as callback doesn't differ from c function as
callback.

Except that they have different types, and there is no
convertion between them which is guaranteed to work.
 
J

Jay

Hi All,

Thanks a lot for your replies.

My problem is as stated by Zachary Turner.

But, the issue is I need a one to one mapping between C callbacks and C
++ Objects.

I have many C++ callback objects.When the 'C' callback function is
called, I need to know which corresponding C++ object's callback
should be called. But, since, in case of 'C' I can only set one
function as callback, I will not get to know which corresponding C++
object's callback should be called.

I guess the best solution will be to modify the 'C' callback to take
Opaque objects as I am unable to come to any other conclusion.

Do let me know if any other work around is available. But, from
whatever I have read so far, no other work around seems to be
possible.

Thanks!

Regards,
Jay
 
N

Noah Roberts

Jay said:
Hi All,

Thanks a lot for your replies.

My problem is as stated by Zachary Turner.

But, the issue is I need a one to one mapping between C callbacks and C
++ Objects.

I have many C++ callback objects.When the 'C' callback function is
called, I need to know which corresponding C++ object's callback
should be called. But, since, in case of 'C' I can only set one
function as callback, I will not get to know which corresponding C++
object's callback should be called.

I guess the best solution will be to modify the 'C' callback to take
Opaque objects as I am unable to come to any other conclusion.

Do let me know if any other work around is available. But, from
whatever I have read so far, no other work around seems to be
possible.

Most C callback API's allow you to pass a void * containing "client
data". Set the client data to the function to call and build one C
function to distinguish between them and call the correct one. Consider:

void callback(int what, double ever, int it_sends, void * client_data)
{
typedef boost<void(int,double,int)> cb_functor;
cb_functor * f = static_cast<cb_functor*>(client_data);
(*f)(what, ever, it_sends);
}

You then need to make sure to construct a boost functor of *exactly that
signature* and pass it into the client data. You're losing type safety,
but that happens any time you mess with C functions. You can gain it
back by limiting the areas that construct the thing and make sure you do
it right....or accept that type by a function that passes it to the
callback mechanism.
 
K

Kram

I'm not sure I get the difficulty here, maybe I'm missing something
but I had to tackle this very same problem this summer.
I needed to interface some C++ code with a C library for speech
recognition. The C++ code provided the audio while the
C code provided the speech recognition. I had to register several call
backs.
To do this I created one extern "C" function for every C++ function I
needed to wrap, using them as sort of pass through functions.
As for needing to have more then one callback function for each
callback just create one extern "C" callback that cal a series of
"wrapped" C++ functions.
 

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

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top