5

We have a structure that accepts C function pointers:

int one(int x)
{
}

int two(int x)
{
}

struct Cstruct
{
    int (*fn1)(int);
    int (*fn2)(int);
};

Now I have a C++ class that has below methods:

class A
{
public:
    int one(int x)
    {
    }

    int two(int x)
    {
    }

    int three(int x)
    {
        struct Cstruct cstr = {&this->one, &this->two};
    }
};

While trying to initialize class A methods address to a instance of Cstruct compiler is giving error of an invalid conversion?

How can I assign the Class member function address to Cstruct?

6
  • Member functions pointers != function pointers. Commented Sep 25, 2018 at 18:21
  • 2
    Member functions are not equal to non-member functions. The big difference being that (non-static) member functions needs an object to be called on. Therefore they can't be used as pointers to non-member functions, and passed to C functions for callbacks. And no, using this when getting the pointer won't help, as it's still a pointer to the function only. Commented Sep 25, 2018 at 18:21
  • Function pointers are different from member function pointers. You want to use the syntax int (A::*fn1)(int);. You will also need an instance of A to call the function from. Commented Sep 25, 2018 at 18:22
  • Member functions have a hidden this as first parameter, so the type of A::one actually looks something like int (*fn)(A*, int) Commented Sep 25, 2018 at 18:23
  • There could be a way around the problem, if the structure have some kind of user-data member or pointer. Then you could set that pointer to the object, and have a function-pointer to a non-member function (or a static member function) which takes the user-data pointer and cast it to the proper type and call the actual member function. Commented Sep 25, 2018 at 18:24

1 Answer 1

9

You cannot do it, because C++ pointer to a non-static member function is not compatible with a non-member function pointer type. This is because member functions require an additional argument - the object on which the member function needs to be called, which becomes this pointer inside the invocation.

If you make your member functions static, your code would compile. However, it would not necessarily do what you want to achieve, because one and two have no access to other non-static members of A.

A trick to passing member functions to C functions requires passing an additional void* pointer with the "registration" record, and having C code pass it back to your static callback functions:

struct Cstruct
{
    void *context; // Add this field
    int (*fn1)(void*, int);
    int (*fn2)(void*, int);
};

class A
{
public:
    static int oneWrap(void* ptr, int x)
    {
        return static_cast<A*>(ptr)->one(x);
    }

    static int twoWrap(void* ptr, int x)
    {
        return static_cast<A*>(ptr)->two(x);
    }

    int one(int x)
    {
    }

    int two(int x)
    {
    }

    int three(int x)
    {
        struct Cstruct cstr = {this, &this->oneWrap, &this->twoWrap};
    }
};

C code would need to pass the value of context to fn1 and fn2:

cs.fn1(cs.context, 123);
cs.fn2(cs.context, 456);
Sign up to request clarification or add additional context in comments.

2 Comments

Is there no other way to achieve the same - can we create an object of the class and then assign it?
@Programmer There is, but your C function needs to "cooperate". Please see the edit.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.