1

私はwxWidgets(C ++、MSVC)でGUIをセットアップしていて、機能の一部はDLLを介してGUIに要素を追加することです。基本的に、私はサイザーを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ではなく、OSにネイティブであるため、メッセージボックスは正常に機能します。

WXUSINGDLL;WXMAKINGDLL;を追加してみました。DLLプロジェクトとAppプロジェクトの両方のMSVCのプリプロセッサ定義で。DLLは正常にコンパイルされますが、その場合はアプリをコンパイルして例外を取得することもできません。

誰かがこの問題を修正する方法を知っていますか?

4

1 に答える 1

2

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;
}
于 2012-12-02T23:25:16.953 に答える