• 12
• 12
• 9
• 10
• 13

# DLL-Based Plugins

This topic is 1252 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I'm working on a user-friend editor front-end for my engine right now for my artists, and I'm want to make it extensible. For example, if I wanted to add a new widget to the UI, I could just write a plugin as a DLL, go the Add-Ons menu, and enable it once it appears in the window. Does this sound a good way to go?

If so, I'd like to expand on this idea, and allow the designers to run the game in-editor. The programmer could write the game logic in C++ in the IDE of their choice, and build the project as a DLL. The editor could be designed to have an "Application Library Path" field in the Project Settings so the editor can find the DLL when successfully compiled. Then, all the Designer has to do is run the application. The problem would be coming up with a solution to profile crashes and performance... I'd have to write some sort of stack trace solution, and the editor-DLLs need to be written with Debugging symbols.

##### Share on other sites

I'm seconding ApochPiQ on this one, I've done DLL-based plugin systems before and I've worked with a lot of projects involving multiple DLLs at once at work and there are just a ton of ways things can get in a messed up state.

The things mentioned above are definitely some of the worst aspects of them, especially keeping memory ownership within DLL borders can be very non-trivial.

Keeping DLL plugins compatible with newer revisions of your codebase can be a huge pain as well.

##### Share on other sites
If you're doing native DLLs (C, C++, etc), then it's going to be somewhat of a pain like Apoch says.

If you're using .Net-based DLLs (C#, VB.Net, etc), they are much less restrictive and MUCH more convenient to create and use.

Depending on how much work you want to put into it, it is also possible to have a (primarily) native C++ executable host .Net DLL plugins. Though this is still much more painful than when the EXE and DLLs are all .Net. Edited by Nypyren

##### Share on other sites

As others' are pointing out these difficulties, it might well be the better long-term solution to have such 'plugins' in the form of scripts. You could package such plugins -- resources, code, configuration, manifest -- inside a .zip file to keep it all together. That's basically what Visual Studio's .vsix extensions are, except they use .net dlls for code.

Scripting should be fine for UI extensions performance-wise, but it does introduce a dependency that you wouldn't have otherwise. Lua would probably make a good choice.

##### Share on other sites

Yeah, they'd be native DLLs. As far as allocating memory goes, I won't be freeing it up across boundaries. When the Editor application loads the DLL up, it'll have a pretty hands-off interaction with the plugin. All plugins will have Create and Destroy() functions that'll be called immediately after loading the DLL and right before unloading the DLL. It's up to the plugin's author to allocate data in Create() and release it in Destroy(), and the Editor application won't ever do any of that directly.

The Editor application will only make function calls to the DLL, and won't access any data directly. As far as exception handling goes, here's a scenario I've thought of for updating the game DLL:

void Editor::Update(float elapsedTime)
{
try {
if(game != null)
game->Update(elapsedTime);
} catch(Exception e) { ... }
}


Assuming my "game" pointer is pointing to the Game subclass in my DLL, and valid, it should run, hopefully! I put the try-catch block there in case there is an exception because I don't want the Editor to crash if the Game DLL causes an exception. Would this be considered as exception handling across binaries? Also, my engine's code might be a separate DLL as well.

If this is a pretty hairy way to approach a plugin system, are there any other good alternatives? I've thought about implementing LUA into my Editor for plugins, but I'd want C++ for testing the game.

##### Share on other sites

I think, though, what everyone is trying to warn you off of, is that native DLLs aren't straightforward. Its not easy like implementing an interface -- its like that, except that the interface *also* consists of a dozen or three sort-of-hidden settings and dials that all have to be exactly in sync -- the right calling conventions, the same ABI, the same behavior settings for floating-point code (potentially), the same data packing on shared structures (or a mutually agreed upon serialization). A dozen compiler settings you probably never think to touch suddenly become critically important. In general, I'd stick my neck out as far as saying that native-code DLL plugins are largely out of favor -- people will put up with it where performance is a necessity, but it seems like too much trouble when its not.

[EDIT] I realize now that the post above was probably in response to nypyren, and that you weren't justifying sticking to native DLLS in the face of my previous post. I'll leave this here for posterity, but apologize that the tone might be a bit harsh in retrospect.

Edited by Ravyne

##### Share on other sites

Would this be considered as exception handling across binaries

Yes, you are assuming that an exception thrown in Game::Update can be caught by your editor, which might not be possible.

##### Share on other sites

I put the try-catch block there in case there is an exception because I don't want the Editor to crash if the Game DLL causes an exception. Would this be considered as exception handling across binaries?

It would. If you were to stick to native plugins and DLL architecture, one approach is to marshall exceptions across the DLL boundary. A simplistic way of doing this is to surround your plugins in a catch(...) so that no exception leaks from the DLL (you can also catch and handle specific exceptions in the same place) -- then, just have your DLL function log the exception data as a dump, and pass back an integer value that indicates the type of the exception. Your client can look up the error code and present the user with a basic description of the exception, and point them to the log for more information -- if necessary, certain error codes might mean for your client to throw the indicated exception itself, as a means of propagating the error to where it can be handled correctly.

##### Share on other sites

The general problem with DLLs is that you have no control how they were created.

There is no standardized C++ ABI.

Do they include their own version of the stdlib functions? Do they include the stdlib as a shared library themselves?

If they were created with a different compiler the class layout maybe be very different and so passing objects between your code and the DLL's code may result in crashes or other undefined behaviour.