首页 > 解决方案 > 跨 DLL 边界的简单回调函数

问题描述

我的原始代码库相当长,我试图将其减少到最低限度。

基于wxWidgets,我一直试图在我的dll中设置一个回调,一旦dll完成了它需要做的事情,它就会触发我catalog_class.cpp中的一个函数。

DLL 已正确加载_handle = LoadLibrary(_pathToLib.c_str())),我可以访问我的所有函数并能够来回传递数据。此外,似乎我可以毫无错误地传入我的回调函数。

但是,每次我的 DLL 尝试调用回调函数时,都会导致错误的函数调用异常。

我注意到的另一件事是,如果我创建如下所示的单行语句,我会收到一条令人困惑的错误消息。

instance->CallbackFoundParts(std::bind(&DIALOG_CATALOG_PART_PICKER::PartsFound, this, std::placeholders::_1));

在此处输入图像描述

似乎某种 DLL 边界存在问题,好像我只是在没有 DLL 的情况下对其进行测试,一切正常。

我的 main.h:

#include <wx/wx.h>

class MyApp : public wxApp
{
public:
    virtual bool OnInit();
};

我的 main.cpp:

    #include "main.h"
    #include "dialog_catalog_part_picker.h"
    
    IMPLEMENT_APP(MyApp)
    
    bool MyApp::OnInit()
    {
        auto *msgs = new DIALOG_CATALOG_PART_PICKER(new wxWindow(), wxT("Messages"));
        msgs->ShowModal();
    
        return true;
    }

我的 dialog_catalog_part_picker.h 的一部分:

class DIALOG_CATALOG_PART_PICKER : public DIALOG_CATALOG_PART_PICKER_BASE {
public:

    DIALOG_CATALOG_PART_PICKER(wxWindow *parent = nullptr, const wxString &aSearchTerm = "");

    ~DIALOG_CATALOG_PART_PICKER();

private:

    void PartsFound(int driverID);

};

我的 dialog_catalog_part_picker.cpp 的一部分:

DIALOG_CATALOG_PART_PICKER::~DIALOG_CATALOG_PART_PICKER() {}

DIALOG_CATALOG_PART_PICKER::DIALOG_CATALOG_PART_PICKER(wxWindow *aParent, const wxString &aSearchTerm) : DIALOG_CATALOG_PART_PICKER_BASE(aParent) {
     if (wareHouse.OpenLib()) {

     std::shared_ptr<IWareHouse> instance = wareHouse.GetInstance();
        
      //Skip if not a valid driver
      if (instance == nullptr)
         continue;
        
      /*** Make sure we bind the callback function ***/
      auto callback1 = std::bind(&DIALOG_CATALOG_PART_PICKER::PartsFound, this, std::placeholders::_1);
      instance->CallbackFoundParts(callback1);

      instance->connectToWarehouse(1);
   }

   // Do some other stuff
   .....

}

// My callback function
void DIALOG_CATALOG_PART_PICKER::PartsFound(int driverID) {
    std::cout <<  "Driver ID: " << driverID <<std::endl;
}

我的 DLL interface.h 的一部分

class IWareHouse
{
public:
    virtual void CallbackFoundParts(std::function<void(int)> f) = 0;

    virtual bool connectToWarehouse(int driverID) = 0;
};

我的 DLL 仓库.h 的一部分

class WareHouse : public IWareHouse {
public:
    WareHouse();

    ~WareHouse();

    void CallbackFoundParts(std::function<void(int)> f) override;

    bool connectToWarehouse(int driverID) override;

private:

    int m_driverID;

    std::function<void(int)> fCallbackFoundParts;

};

我的 DLL 仓库.cpp

bool WareHouse::connectToWarehouse(int driverID) {

    // save assigned driver ID, this ID is assigned randomly by the caller
    m_driverID = driverID;

    try {
        fCallbackFoundParts(driverID);
    }
    catch (const std::exception& exc)
    {
        // catch anything thrown within try block that derives from std::exception
        std::cerr << exc.what() << std::endl;
    }

    return true;
}

void WareHouse::CallbackFoundParts(std::function<void(int)> f) {
    fCallbackFoundParts = f;
}

标签: c++dllcmakecallbackstdbind

解决方案


推荐阅读