类中 dll 的回调函数

Posted

技术标签:

【中文标题】类中 dll 的回调函数【英文标题】:Callback function from a dll within a class 【发布时间】:2021-04-30 11:51:13 【问题描述】:

我编写了一个 c++ dll,它允许我从主应用程序注册一个回调函数。 这是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.


在主应用程序中,我像这样注册回调:

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);
       

这没有问题。但现在我希望 ReadHSCallBack 成为 Form1 类的成员。 所以我将其更改为以下内容:

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 也获得 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);
       

然后我们开始:它无法编译。导致错误的行是

 valr(&ReadHSCallBack);

错误说明是: [bcc32 错误] Main.cpp(11422): E2034 将 'void (__stdcall * (_closure )(unsigned char *,unsigned long *))(unsigned char *,unsigned long *)' 转换为 'void (__stdcall *)( unsigned char *,unsigned long *)' 不可能。

我不知道如何处理那个 __closure 声明。我也试过 valr(&this->ReadHSCallBack) 这也无济于事。

【问题讨论】:

您可以使用非静态成员函数作为回调,因为 (a) 它们不是简单的函数指针,并且 (b) 它们需要调用对象。 【参考方案1】:

不使用函数指针,可以使用std::function吗?

我一直都在回调类方法,尽管我使用 lambdas。这是一个例子:

typedef std::function<void(const char *)> CallbackFunction;

这是传递符合该签名的内容的一种方式:

vec.addArg("port", [&](const char *arg) port = atoi(arg); , "p", "Set listen port. Default is 9300.");

到目前为止,这是从我目前正在处理的程序中剪切和粘贴的实际代码。 lambda 可以做任何事情,所以我可以这样做:

vec.addArg("port", [=](const char *arg) foo(arg); );

请注意,我使用 = 而不是 &。

你可以做整个 std::bind() 的事情,但我觉得那很难看,宁愿传递一个 lambda。

使用 C 风格的函数指针非常像 C,C++ 程序员应该使用现代方法。这意味着 std::function 和可能的 lambdas。

【讨论】:

嗨 Joseph,不幸的是,我使用的 IDE 不是现代的……它甚至不支持 std::function。根据这个***.com/a/7132549/9368347,它使用pre c++98 标准。它是 Embarcadero C++Builder 10.1。不幸的是我没有额外的更新,新版本已经使用了c++17。我想摆脱 c++builder 很长时间了,以至于我犹豫是否要购买进一步的更新。有什么“经典”的方法吗? 首先,这与您的 IDE 支持什么无关。你的编译器支持什么?话虽如此,您是否有某些原因与古老的开发环境联系在一起?您是否正在为一个非常古老的平台编码?如果是这样,那我不知道该告诉你什么。我早就换了 IDE。

以上是关于类中 dll 的回调函数的主要内容,如果未能解决你的问题,请参考以下文章

什么是回调函数,如何写一个回调函数

C语言的回调函数

DELPHI调用DLL时的回调函数问题

回调函数和钩子函数的说明

C#中调用C的DLL中的回调函数,想实现消息响应机制

C#调用C++ dll 回调