Reputation: 15
I have written a c++ dll, which allows me to register a callback function from the main application. This is the according code in the dll:
extern "C" {
typedef void(__stdcall* callbackRead_t)(UCHAR* Buffer, ULONG* BufferSize);
static callbackRead_t s_user_functionRead = nullptr; // variable used to store the user function address
__declspec(dllexport) void public_readfunc_taking_callback(callbackRead_t evHnd)
{
s_user_functionRead = evHnd; // save the callback address for funcA.
}
}
In the main application I register the callback like this:
typedef void(__stdcall *TeventReadHS)(unsigned char* Buffer, unsigned long* BufferSize);
typedef void(__stdcall *eventReadHS)(TeventReadHS eveHnd);
void __stdcall ReadHSCallBack(unsigned char* Buffer, unsigned long* NumRead){
//do something
}
void __stdcall RegisterReadBack(void){
eventReadHS valr;
HINSTANCE handleHSC;
handleHSC=LoadLibrary(L"HSC.dll");
if (!handleHSC){
//Error handling here
}
valr=(eventReadHS)GetProcAddress(handleHSC,"public_readfunc_taking_callback");
if(valr!=NULL){
valr(&ReadHSCallBack);
}
}
That works without a problem. But Now I want ReadHSCallBack to be a member of a class, Form1. So I changed that to the following:
class TForm1: public TForm
{
//a lot of other stuff here
public:
__fastcall TForm1(TComponent* Owner);
void __fastcall TForm1::RegisterReadBack(void);
void __stdcall TForm1::ReadHSCallBack(unsigned char* Buffer, unsigned long* NumRead);
};
RegisterReadback also gets a member of Form1:
void __fastcall TForm1::RegisterReadBack(void){
eventReadHS valr;
HINSTANCE handleHSC;
handleHSC=LoadLibrary(L"HSC.dll");
if (!handleHSC){
//Error handling here
}
valr=(eventReadHS)GetProcAddress(handleHSC,"public_readfunc_taking_callback");
if(valr!=NULL){
valr(&ReadHSCallBack);
}
}
And here we go: it doesn't compile. The line causing the error is
valr(&ReadHSCallBack);
Error statement is: [bcc32 Error] Main.cpp(11422): E2034 Conversion of 'void (__stdcall * (_closure )(unsigned char *,unsigned long *))(unsigned char *,unsigned long *)' to 'void (__stdcall *)(unsigned char *,unsigned long *)' not possible.
I don't have any clue how to deal with that __closure statement. I also tried valr(&this->ReadHSCallBack) that also doesn't help.
Upvotes: 0
Views: 1084
Reputation: 9068
Rather than using function pointers, can you use std::function?
I do callbacks to class methods all the time, although I use lambdas for it. Here's one example:
typedef std::function<void(const char *)> CallbackFunction;
Here's a way of passing something that fits that signature:
vec.addArg("port", [&](const char *arg){ port = atoi(arg); }, "p", "Set listen port. Default is 9300.");
So far, this is cut & paste of actual code from the program I'm currently working on. The lambda can do anything, so I could do this:
vec.addArg("port", [=](const char *arg){ foo(arg); });
Note that I used = for this instead of &.
You can do the whole std::bind() thing, but I find that ugly and would rather pass a lambda.
Using C-style function pointers is very C-like, and C++ programmers should use modern methods. This means std::function and possibly lambdas.
Upvotes: 0