views:

1518

answers:

4

I have a C library that needs a callback function to be registered to customize some processing. Type of the callback function is int a(int *, int *).

I am writing C++ code similar to the following and try to register a C++ class function as the callback function:

class A {
  public:
   A();
   ~A();
   int e(int *k, int *j);
};

A::A()
{
   register_with_library(e)
}

int
A::e(int *k, int *e)
{
  return 0;
}

A::~A() 
{

}

The compiler throws following error:

In constructor 'A::A()',
error:
 argument of type ‘int (A::)(int*, int*)’ does not match ‘int (*)(int*, int*)’.

My questions:

  1. First of all is it possible to register a C++ class memeber function like I am trying to do and if so how? (I read 32.8 at http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html. But in my opinion it does not solve the problem)
  2. Is there a alternate/better way to tackle this?
+10  A: 

You can do that if the member function is static.

Non-static member functions of class A have an implicit first parameter of type class A* which corresponds to this pointer. That's why you could only register them if the signature of the callback also had the first parameter of class A* type.

sharptooth
yes. that solution worked. What confuses me is compiler did not show error int (A::)(A *, int*, int*)’ does not match ‘int ()(int, int*)’
Methos
It did, but by putting (A::) which means that function is part of class A, which from there implies the 'this' pointer.
GMan
I'm just curious... is this specified in the standard? I just glanced at the section on classes and didn't find this. Nevertheless, very interesting. I just wouldn't think that every compiler necessarily has to handle non-static member functions in this way.
Tom
@Methos, saying that member functions have an implicit first parameter doesn't mean that parameter really exist. It means that conceptually, it's there.
Johannes Schaub - litb
Johannes Schaub - litb
+1  A: 

The problem with using a member function is that it needs an object on which to act - and C doesnt know about objects.

The easiest way would be to do the following:

//In a header file:
extern "C" int e(int * k, int * e);

//In your implementation: 
int e(int * k, int * e) { return 0; }
Visage
so you mean do not make it a member function?
Methos
In this case, yes. IMO the greater simplicity afforded by using a standalone function outweighs the lack of encapsulation involved.
Visage
+3  A: 

The problem is that method != function. The compiler will transform your method to something like that :
int e( A *this, int *k, int *j );

So, it's sure you can't pass it, because the class instance can't be passed as argument. One way to work around is to make the method as static, this way it would have the good type. But it won't any class instance, and access to non-static class members.

The other way is to declare a function with a static Pointer to a A initialised the first time. The function only redirect the call to the class :

int callback( int *j, int *k )
{
    static A  *obj = new A();
    a->(j, k);
}

Then you can register the callback function.

Raoul Supercopter
+3  A: 

Well ...if you are on a win32 platform there is always the nasty Thunking way ...

Thunking in Win32: Simplifying callbacks to non-static member functions

It is a solution but I don't recommend using it.
It has a good explanation and it is nice to know it exists.

TimW