Bodo
Bodo

Reputation: 15

Callback function from a dll within a class

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

Answers (1)

Joseph Larson
Joseph Larson

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

Related Questions