Your problem is that the callback type
typedef void (CALLBACK *EventCallback)();
does not have any user-provided data pointer. This is customary for the exact reason that users often need it.
And just for completeness,
Is there any way to cast that member function to a non-member function
No, they're fundamentally different, because non-static member functions must be called with an implicit this pointer, and there's nowhere to store that in a regular function pointer. That's exactly what we'd use the user-provided pointer argument for if the API had one.
Also I don't want to declare My_class::using_API and My_class::API as static member.
How about if we generate another static for each distinct registration? We can automate it by using lambda type uniqueness:
template <typename Lambda>
class TrampolineWrapper
{
inline static std::optional<Lambda> dest_; // optional so we can defer initialization
public:
TrampolineWrapper(some_API *api, Lambda &&lambda)
{
// store your _stateful_ functor into a unique static
dest_.emplace( std::move(lambda) );
// register a unique _stateless_ lambda (convertible to free function)
api->EnableInterrupt(
[](){
(*TrampolineWrapper<Lambda>::dest_)();
},
nullptr);
}
};
// handy type-deducing function
template <typename Lambda>
TrampolineWrapper<Lambda> wrap(some_API *api, Lambda &&lambda)
{
return {api, std::move(lambda)};
}
and use it like
class My_class
{
some_API API;
void my_func() { cout << "This is my_func!\n" }
public:
void using_api()
{
auto wrapper = wrap(&API, [this](){ my_func(); });
// stateful lambda ^^^^
// not directly convertible to a free function
}
};
This depends on the uniqueness of lambda types to work - each lambda you use this with gets a unique static dest_ object of the same type (which may be stateful), and a unique stateless forwarding lambda (which is convertible to a free function for this horrible API).
Note that this is unique only if you have multiple distinct callers registering distinct lambdas. Two calls to My_class::using_api will still collide (the second will overwrite the first's lambda).
The only other nasty thing is that we're discarding the wrapper once the static is set up ... it'd be much nicer to keep it around so we could use it for unregistering the callback or something. You can do this if you want, but since you cannot know its type outside the scope of your lambda, it'll need to do something dynamic.