Skip to main content
GameDev.net gamedev.net
🔒 Locked

Dynamic library plugin initialisation

Started by hymerman Jan 24, 2007 at 8:49 AM 9 replies 3.6k views
Original Post
hymerman
hymerman
Hi folks, I'll keep this short: I've got an application that used plugins, and would like some sort of 'DLLMain'-like function in each dynamic library that initialises everything the plugin needs initialised - registering for messages, registering with factories and so on. There's a plugin manager that loads all dynamic libraries, which is the logical place for this initialise method to be called. The problem I'm having is that this method has to be extern "C"'ed, and this won't work with classes and the like - I haven't tried it out yet, but I've read and been told that using classes across dynamic boundaries is risky, if not impossible. What would you chaps suggest? Any thoughts will be much appreciated. Thanks very much :)
DIB
DIB
I initialize objects inside my extern-c'd DLL entry point. I then register them with a centeral object repository and am able to use them in other DLL's just fine.
Sneftel
Sneftel
Quote:
Original post by hymerman
The problem I'm having is that this method has to be extern "C"'ed, and this won't work with classes and the like

The function needs to be declared as WINAPI (calling convention), but it can still do C++ stuff by calling other functions.
Quote:
using classes across dynamic boundaries is risky, if not impossible.

It's risky in general and easy under certain circumstances. Basically, if your memory subsystem is DLL-based (as is definitely the default in VS2005, and IIRC also in VS2002 and VS2003), and your host app and DLLs are compiled with the same compiler, you have nothing to worry about.
pjcast
pjcast
What you need to have, is in your main application, you use a set of base class interface classes. Then, when you load the dll (which has classes which implement these interfaces) you import a simple C function from the DLL, call that function, which will create the C++ class, and than register it to the main application.

Ogre (for an example, there are many other examples too) follows this. All the plugins are C++ classes inside DLL's which implement the interfaces defined in the main DLL (ogremain.dll).
hymerman
hymerman
This is actually a cross-platform app, which is why I was avoiding mentioning 'DLLs'. Also, there's no guarantee that plugins will be compiled with the same compiler as the app itself, and in fact this is very likely not to be the case. I can, however, guarantee that the code that gets compiled will be the same across machines (unlike the STL, which I understand has varying implementations). Does this improve the situation any?

DIB, it sounds like you're doing what I want to successfully; I think I'll code up what I want and test it out, since hearing that makes me a little more confident I won't be wasting my time :) Thanks!

EDIT:
pjcast; This sounds a lot like the way I want to do it, perhaps I'll have a quick browse of the OGRE source in a minute. Cheers :)
pjcast
pjcast
Quote:
Original post by hymerman
This is actually a cross-platform app, which is why I was avoiding mentioning 'DLLs'.

Doesn't matter, Linux has shared libraries which are equivalent. In fact, there is a way to make a DllMain-like function under Linux shared libraries (using a compiler attribute setting), but I won't go into that. However, you are better off using the imported function from the library and calling that to init your plugin.

Quote:
Original post by hymerman
Also, there's no guarantee that plugins will be compiled with the same compiler as the app itself, and in fact this is very likely not to be the case. I can, however, guarantee that the code that gets compiled will be the same across machines (unlike the STL, which I understand has varying implementations). Does this improve the situation any?

This could be an issue when using C++ plugins. Different compilers would likely use different C++ runtimes, causing conflicts (between memory allocations, stl implementations, ABI issues, etc).

If you really need compiler independence, your best bet is to have your plugins implement regular C function pointers. Internally, the plugins can of course use C++, but to the main application, it only calls C functions.
hymerman
hymerman
EDIT: this is in reply to pjcast

So... could I do something cheeky like have a C function that calls a C++ function, which is where the actual OO stuff is done? Is that likely to backfire? The only things I can think of currently that will be passed across DLL boundaries will be function pointers (for the factories) and ints (for version numbers and the like). Since these are not C++ specific I presume they won't explode or anything, right?
Demus79
Demus79

In every DLL used in my project I implement this "local module class" which is derived from abstract "local module interface class".

When the program loads a DLL, it requests only one function from the DLL : something like GetLocalModule, which is called right after the request. The function returns a pointer to the local module of that specific DLL, which is then added to the list of modules (sort of DLL/Module manager).

The class factory works through the DLL manager. In every module, I can use this local module interface to create an object defined elsewhere

So, in this system, one module can contain one or more different kind of objects. Also, if needed, all the objects can be packed easily inside one big module and it still works without any changes.

Of course, this system expects that all DLLs are loaded in the beginning and not released until the end. But that's not a big con.

Best regards!
pjcast
pjcast
Quote:
Original post by hymerman
EDIT: this is in reply to pjcast

So... could I do something cheeky like have a C function that calls a C++ function, which is where the actual OO stuff is done? Is that likely to backfire? The only things I can think of currently that will be passed across DLL boundaries will be function pointers (for the factories) and ints (for version numbers and the like). Since these are not C++ specific I presume they won't explode or anything, right?


If all your are passing is C function pointers (can be static class member functions too), and primitive types (ints, floats, pointers, etc) you shouldn't have any issues with using internal classes to do the work in an OO manner. And should be able to get away with different compilers/C++ runtimes on different libraries loaded by your program. However, don't qoute me on that as I have never tried it myself. Also, you shouldn't try to throw an exception out of your plugin that will be caught by the main app/library - basically, anything C++ should stay localized to the plugin.
hymerman
hymerman
Demus79, I like your idea of a 'local module interface' class; we've got something like this in our current code, but I never thought of it as an interface to the module. I like this terminology, it makes everything feel 'right' again!

Overall though, looks like this whole shared library lark is a lot more work than I realised. Cheers for your help and warnings, everyone, I think I know enough to get on and implement this properly now :)

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.