【问题标题】:wxWidgets - Add items to sizer via DLLwxWidgets - 通过 DLL 将项目添加到 sizer
【发布时间】:2012-11-20 10:12:12
【问题描述】:

我有一个使用 wxWidgets(C++、MSVC)设置的 GUI,部分功能是通过 DLL 向 GUI 添加元素。本质上,我会将一个 sizer 传递给 DLL,然后它会根据 DLL 中的内容添加元素。

有人可以为我指出如何设置 DLL 的正确方向吗?我看过,但没有看到任何与我正在寻找的相似的东西。元素的编程对我来说很好,我只需要了解如何构造 DLL 编程。

帮助表示赞赏。


更新

我做了类似于http://wiki.wxwidgets.org/Programs_That_Support_Plugins的事情。

基本上,每当我尝试使用 DLL 中的 wxWidgets 组件时,都会遇到访问冲突读取位置错误。

在samplePlugin.cpp中,如果我使用

void samplePlugin::PerformTasks()
{
   wxMessageBox(_("I would if I could..."));
}

我得到了错误。但是,如果我使用

void samplePlugin::PerformTasks()
{
   MessageBox(0,"Testing this thing","Test",0);
}

不是 wxWidgets,而是操作系统原生的,消息框可以正常工作。

我已经尝试添加 WXUSINGDLL;WXMAKINGDLL;在 DLL 和 App 项目中的 MSVC 中的预处理器定义中。 DLL 编译得很好,但在这种情况下我什至无法编译应用程序并获得异常。

有人知道如何解决这个问题吗?

【问题讨论】:

  • "根据 DLL 中的内容添加元素。"那么,DLL 中有什么?请举例说明“在 DLL 中”和添加的元素。
  • 假设我在标签、单选按钮等的 DLL 中有代码。我想将这些小部件添加到我从主 GUI 应用程序传入的 sizer 中。
  • 这个问题没有多大意义,因为从 DLL 添加 sizer 元素与从主应用程序添加它们根本没有区别。您的问题似乎更多关于“我如何编写 DLL”,但它太笼统了。
  • 好吧,VZ,我认为这些问题对于 wxWidgets 开发来说是正常的。官方论坛上有几个关于此的主题,但它们并没有太大帮助。没有 wxWidgets 的非 GUI DLL 和使用 wxWidgets 的 DLL 之间存在差异。例如。您需要使用多线程调试DLL/多线程DLL编译器设置,否则将不起作用。在实现这样的插件之前,我个人不得不花费大量时间挖掘论坛并尝试不同的编译器/链接器设置和 DLL 结构(例如,在 DLL 中使用和不使用应用程序类)。但现在它毕竟看起来微不足道。
  • 您好,您可以看看我的原帖吗?我添加了一个更新。谢谢。

标签: c++ visual-c++ user-interface dll wxwidgets


【解决方案1】:

创建一个 DLL 项目并指定预处理器指令,例如/DIFLOOR_EXPORTS_COMMONPLUGINBASE(此预处理器变量仅在 DLL 项目中)

然后创建一个标头来指定您的类是导入还是导出:

CommonPluing.h

#ifndef _COMMONPLUGIN_H
#define _COMMONPLUGIN_H

#if defined(__WXMSW__)
#ifdef IFLOOR_EXPORTS_COMMONPLUGINBASE
#define IFLOOR_API_COMMONPLUGINBASE __declspec(dllexport)
#else
#define IFLOOR_API_COMMONPLUGINBASE __declspec(dllimport)
#endif
#else
#define IFLOOR_API_COMMONPLUGINBASE
#endif

#endif // _COMMONPLUGIN_H

然后创建导出的类并从第一个标题添加说明符:

CommonConfigWindowBase.h

class IFLOOR_API_COMMONPLUGINBASE CommonConfigWindowBase : public wxPanel 
{
    DECLARE_DYNAMIC_CLASS(CommonConfigWindowBase)
public:
    /// Constructors
    CommonConfigWindowBase();
    CommonConfigWindowBase(wxWindow *parent,
        wxWindowID winid = wxID_ANY,
        const wxPoint& pos = wxDefaultPosition,
        const wxSize& size = wxDefaultSize,
        long style = wxTAB_TRAVERSAL | wxNO_BORDER,
        const wxString& name = wxPanelNameStr);

    /// Pseudo ctor
    bool Create(wxWindow *parent,
        wxWindowID winid = wxID_ANY,
        const wxPoint& pos = wxDefaultPosition,
        const wxSize& size = wxDefaultSize,
        long style = wxTAB_TRAVERSAL | wxNO_BORDER,
        const wxString& name = wxPanelNameStr);

    virtual ~CommonConfigWindowBase();

    /// Reads config from the effect
    virtual bool ReadConfig(){return true;}

    /// Saves config to the effect
    virtual bool SaveConfig(){return true;}
};

创建可从主可执行文件调用的导出函数(您可能希望创建一个包装类并调用返回 wxWindow * 的方法)。 您需要一个导出的方法来创建插件对象和删除它。你还需要一个!!!虚拟析构函数!!!对于导出的对象和您的窗口。 所以假设 SportEffectPlugin 包含一个 wxWindow * CreateConfigWindow(wxWindow * parent) 方法:

Exports.cpp

#include "stdwx.h"
#include "CommonConfigWindowBase.h"

IFLOOR_API_COMMONPLUGINBASE IFloorEffectPluginBase * CreatePlugin(const wxString& sBasePath, iFloorBlobVector * blobs)
{
    return new SportEffectPlugin(sBasePath, blobs);
}

IFLOOR_API_COMMONPLUGINBASE void DeletePlugin(IFloorEffectPluginBase * plugin)
{
    wxDELETE(plugin);
}

然后在主应用程序中加载 DLL(您需要根据需要采用以下代码):

Loader.cpp

bool IFloorSystem::LoadPlugins(bool forceProgramPath)
{
    if (!m_DefaultPlugin)
    {
        m_DefaultPlugin = new DefaultEffectPlugin(GetDefaultGraphicsPath());
        RegisterEffectPlugin(m_DefaultPlugin);
    }

    wxFileName fn;
    fn.AssignDir(GetPluginsPath(forceProgramPath));
    wxLogDebug(wxT("%s"), fn.GetFullPath().data());
    fn.AppendDir(wxT("effects"));
    wxLogDebug(wxT("%s"), fn.GetFullPath().data());
    if (!fn.DirExists())
        return false;
    wxDir dir(fn.GetFullPath());
    if (!dir.IsOpened())
        return false;

    // scan for plugins
    wxString filename;
    wxString ext = wxT("*.dll"); // TODO: change ext for different platforms
    bool bFound = dir.GetFirst(&filename, ext, wxDIR_FILES);
    while (bFound)
    {
        fn.SetFullName(filename);
        wxDynamicLibrary * dll = new wxDynamicLibrary(fn.GetFullPath());
        if (dll->IsLoaded())
        {
            wxDYNLIB_FUNCTION(CreatePlugin_function, CreatePlugin, *dll);
            if (pfnCreatePlugin)
            {
                IFloorEffectPluginBase* plugin = pfnCreatePlugin(GetDefaultGraphicsPath(), &IFloorStorage::Instance().GetBlobs());
                RegisterEffectPlugin(plugin);
                m_DllList.Append(dll);
                m_MapPluginsDll[plugin] = dll;
            }
            else
                wxDELETE(dll);
        }
        bFound = dir.GetNext(&filename);
    }
    return true;
}

最后你需要通过调用DLL中的函数来卸载插件并删除所有加载的对象:

bool IFloorSystem::UnRegisterEffectPlugin(IFloorEffectPluginBase * plugin)
{
    IFloorEffectPluginBaseList::compatibility_iterator it = m_Plugins.Find(plugin);
    if (it == NULL)
        return false;

    do 
    {
        wxDynamicLibrary * dll = m_MapPluginsDll[plugin];
        if (!dll) // Probably plugin was not loaded from dll
            break;

        wxDYNLIB_FUNCTION(DeletePlugin_function, DeletePlugin, *dll);
        if (pfnDeletePlugin)
        {
            pfnDeletePlugin(plugin);
            m_Plugins.Erase(it);
            m_MapPluginsDll.erase(plugin);
            return true;
        }
    } while (false);

    // If plugin is not loaded from DLL
    wxDELETE(plugin);
    m_Plugins.Erase(it);

    return true;
}

【讨论】:

  • 您好,您可以看看我的原帖吗?我添加了一个更新。谢谢。
  • 这是我在 CMake 脚本中的内容(预处理器定义): set(PREPROCESSOR_DEFINITIONS ${PREPROCESSOR_DEFINITIONS};/D_US​​RDLL;/DIFLOOR_EXPORTS_COMMONPLUGINBASE;/D__STDC_CONSTANT_MACROS) - 你可以看到 CommonPlugin 中使用了 IFLOOR_EXPORTS_COMMONPLUGINBASE。用于定义 IFLOOR_API_COMMONPLUGINBASE 宏,该宏包含 DLL 类的导出说明符。另外不要忘记您需要将 wxWidgets 构建为 DLL,并将运行时库用作多线程调试 DLL(用于调试)和多线程 DLL(用于发布)以及 DLL 和主机应用程序中的相同选项。
  • 这是我在 DLL 的预处理器定义中的定义:WIN32;_WINDOWS;NDEBUG;WXUSINGDLL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_UNICODE;__WXDEBUG__=1;_USRDLL;IFLOOR_EXPORTS_COMMONPLUGINBASE;CMAKE_INTDIR_EXPORTSonPlugin;; %(预处理器定义)
  • 主机应用的预处理器定义:WIN32;_WINDOWS;NDEBUG;WXUSINGDLL;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_UNICODE;__WXDEBUG__=1;_USRDLL;wxUSE_NO_MANIFEST=1;__STDC_CONSTANT_MACROS;CMAKE_INTDIR="Release"预处理器定义)
  • 感谢您提供的信息,我已经开始工作了。不过,我还有另一个问题。我有一个 wxNotebook,基本上我在每个页面中加载了不同的 dll。我将如何浏览页面,然后在任何时间点使用其特定的 dll?
猜你喜欢
  • 1970-01-01
  • 2011-02-07
  • 2014-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多