Subscribe to gabehabe's on-topic ramblings        RSS Feed
-----

wxWidgets: Loading symbols from DLLs at runtime

Icon Leave Comment
[Apologies if the entry is a little unclear, I just threw this together in about 10 minutes, I wanna get it out there... it's fucking hard to find any sort of information when it comes to this at the moment]

Quick entry, gonna turn this into a tutorial soon. The code is a bit of a mess, since I was just throwing stuff together while I was figuring this out. I'll tidy it up when it's tutorial tiems.

Basically, I recently developed a plugin system for my snippet manager. The way it works is simple: It loads symbols from a DLL into the application, which can be called from a dynamically created menu. First off, the main code [this is the messy bit for the time being]

This code opens a subdirectory within the working directory called "plugins", and grabs all the DLLs from them. If the DLL contains a symbol called SnippetManagerPluginMain (the only required symbol for the plugins, I kept them simple) it will add it to the menu.

Additionally, it also checks for two optional optional symbols, which are pretty cool. They simply return strings, which assign the name and the keyboard shortcut for the plugin. If neither is set, it has no keyboard shortcut, and the name defaults to the name of the DLL file.
    /// <PLUGIN SYSTEM> <!-- ALPHA! -->
    #if defined(__WXMSW__) // windows plugins - load ./plugins/*.dll
    if(wxDir::Exists(wxT("./plugins/"))) {
        wxDir plugin_dir(wxT("./plugins/"));
        if(plugin_dir.HasFiles()) {
            wxArrayString files;
            wxDir::GetAllFiles(wxT("./plugins/"), &files);
            wxMenu* plugin_menu = new wxMenu(wxT(""));
            wxDynamicLibrary* lib;
            wxString label;
            char* ks;
            bool showmenu = false;
            for(unsigned int i = 0; i < files.GetCount(); i++) {
                lib = new wxDynamicLibrary();
                if(files.Item(i).Find(wxT(".dll")) != -1) {
                    lib->Load(files[i]);
                    if(lib->HasSymbol(L"SnippetManagerPluginMain")) {
                        showmenu = true;
                        if(lib->HasSymbol(L"SnippetManagerPluginName")) {
                            label = wxString(((SnippetManagerPluginName)lib->GetSymbol(L"SnippetManagerPluginName"))(), wxConvUTF8);
                        } else {
                            label = files[i].AfterFirst('\\').AfterFirst('\\').BeforeLast('.');
                        }
                        this->plugins.push_back((SnippetManagerPlugin)lib->GetSymbol(L"SnippetManagerPluginMain"));

                        if(lib->HasSymbol(L"SnippetManagerKeyboardShortcut")) {
                            ks = ((SnippetManagerKeyboardShortcut)lib->GetSymbol(L"SnippetManagerKeyboardShortcut"))();
                            label += L"\t" + wxString(ks, wxConvUTF8);

                        }
                        plugin_menu->Append(wxID_PLUGIN + i, label);
                        Connect(wxID_PLUGIN + i, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(Snippet_ManagerFrame::handle_plugin));
                    }
                }
            }
            if(showmenu) {
                mbar->Append(plugin_menu, wxT("&Plugins"));
            }
        }
    }
    #endif
    /// </PLUGIN SYSTEM>


In order to bind the events to the menu, the ::Connect method is called. This is an alternative to using EVENT_TABLE, and allows events to be allocated dynamically at runtime. wxID_PLUGIN is a custom variable, and basically, any of the menu items within the menu will call the main frame's handle_plugin method. The important part, however, is the fact that each one has a different ID, even though they use the same method.

The method itself then uses the ID of the event calling it to lookup the DLL's symbol, which were added in this->plugins.
void Snippet_ManagerFrame::handle_plugin(wxCommandEvent &e) {
    this->plugins[e.GetId() - wxID_PLUGIN](this->ui->uid.mb_str(), fill_p_snip(this->ui->get_active_stc()->snip, this->ui->get_active_stc()->GetText()));
}


Of course, some of the code here doesn't really mean jack all, since there are custom methods and stuff used in it. But the base of it is clear. I'll try to write another (small) application and a tutorial covering the steps over the weekend.

Until then, have fun! :)

0 Comments On This Entry

 

August 2014

S M T W T F S
     12
3456789
10111213141516
171819202122 23
24252627282930
31      

Request A Topic!

Want me to blog about something? Perhaps a language? A piece of software? A specific topic? Let me know! Even guests can post here on my blog!

If you would like to request a topic, please post a comment here and I'll get on it right away! smile.gif

Search My Blog

0 user(s) viewing

0 Guests
0 member(s)
0 anonymous member(s)

gabehabe's off-topic ramblings

Follow me on Twitter!
lol, my other blog died a horrible lonely death. Ah well.

Smiley of the [however often I change it]

IPB Image

Contact Me

e-mail: gabehabe@gmail.com

Google Talk: gabehabe@gmail.com
MSN: gabehabe@hotmail.com
Yahoo: gabehabe (rarely used)
AIM: gabehabe (rarely used)

Skype: gabehabe

Want me to work for you? [click]