gpt4 book ai didi

c++ - wxWidgets - 通过 DLL 添加项目到 sizer

转载 作者:行者123 更新时间:2023-11-28 07:51:30 25 4
gpt4 key购买 nike

我有一个使用 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 项目并指定预处理器指令,例如/DIFLOOR_EXPORTS_COMMONPLUGINBASE(此预处理器变量仅在 DLL 项目中)

然后创建一个 header ,指定您的类是导入还是导出:

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

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

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) 方法:

导出.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;
}

关于c++ - wxWidgets - 通过 DLL 添加项目到 sizer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13674887/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com