#### Archived

This topic is now archived and is closed to further replies.

# ANWTH : Interface based plug in systems Part 1

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

## Recommended Posts

Hi, I have some time to spend so I think I'll start up a programming speech session called : Articles No-one Wanted To Have (ANWTH) Be welcome to the first topic based on Plug-Ins Systems : Interface based plug in systems Part 1 You can't decline it : You already have thought of an easy and fast way to include new features to your game, your engine or your tools ! You can't tell me you haven't ! Since you already have thought of it, why don't you just do it ? Too much hassle ? Too much work ? Nah, it's easy ! 1. The basis. OS such like Windows already use and provide possibilities to dynamically load code that is executed on demand : It's called DLL. A DLL isn't anything else than a set of functions that are accessible through an interface or by a simple pointer to the function. 1.1 Function definition. The first thing you have to do is to define a prototype of the function you want to use within a given DLL. It doesn't really matter what the parameter list looks like or what type the return value is of. All that matter is that everything you use within the definition of the function is available at the point of definition. You want to use a pointer to a structure as a return pointer ? Define the structure before you use it in the function definition. So the first thing we have to define are the function prototypes that allow the access to the functions in the DLL. Here's such a definition :
typedef bool (__cdecl * CANBEUNLOADED)(void);
Let's take a look at the different parts of this definition : typedef - a typedef lets you define a new data type name. In our example we want to define a new type called CANBEUNLOADED. bool - our return type should be of boolean type. Now the tricky part : __cdecl - This keyword declares the following variable or function as using the C-Style naming conventions. For a function this means that it effects how the parameters are passed (last parameter is pushed first, and the caller cleans up the stack). * - It's a pointer. CANBEUNLOADED - This is the name of the new data type name. For the declaration the next elements are important because like this we know that we define a function. If we wanted to just define a new data type name, we would have left out the next element. (void) - The parameters to pass. Here we declare that it is void. What have we defined ? We have defined a new data type which is called CANBEUNLOADED and which is a function taking no parameters and returning a boolean. The usage is quite simple too :
// Declare a function.

// Put in a pointer (you got from somewhere).
TheFunction = FunctionPointer;

// Call it.
bool bResult = TheFunction();     
It's as easy as that. 1.2 Exporting the function of a DLL. After we have defined the prototype of our functions, we'll have to put them into a DLL and make them accessible from outside the DLL. This isn't quite difficult either. Here's a small function that, once placed into the source code of an DLL, is accessible from outside the DLL :
extern "C" __declspec(dllexport) bool __cdecl CanBeUnloaded(void)
{
return (0 == g_refCount);
}     
char sOldWorkingFolder[MAX_PATH];
GetCurrentDirectory(DIM_OF(sOldWorkingFolder), sOldWorkingFolder);
SetCurrentDirectory(_psLibFolder);     
Later on (after you have loaded the DLL) you set the current directory back to the old one :
SetCurrentDirectory(sOldWorkingFolder);
In between you load the DLL. Windows has a nice function for that, too : LoadLibrary. The usage :
HINSTANCE libInstance;
libInstance = LoadLibrary(_psLibPath);     
_psLibPath is the path and filename of the library (DLL) to open. If Windows was able to open it, you'll get a valid HINSTANCE. If not the returned value is 0x00000000. That's it... the library (DLL) has been dynamically loaded. 1.4 Getting pointer to functions. What we now want is to get the pointer of the functions out of the DLL we just have opened. That's not difficult. All you need is one function and two parameters :
CANBEUNLOADED pfCanBeUnloaded = NULL;
pfCanBeUnloaded = (CANBEUNLOADED) GetProcAddress(libInstance, "CanBeUnloaded");     
We use the in 1.1 defined function CANBEUNLOADED. The above line tries to get the pointer to the function "CanBeUnloaded" located in the DLL whose handle is stored in libInstance. Since the function returns the pointer to the function we simply cast it and store it in our function pointer variable. If the function fails, the return value is NULL so always check if you got a valid pointer before making any call. The first GetProcAddress parameter is always the handle to the instance of the loaded DLL. The second parameter is the name of the function to load. NOTE : Pay attention to the spelling of the function name. It must be *exactly* the same you've used to export the function from the DLL. If you make a mistake (ie. lower char instead of upper char) then the function pointer will not be found. 1.5 Free the DLL. If you don't need the DLL anymore, you'll have to unload it. Don't do this when you want to continue the functions you retrieved from the DLL ! The pointer will be invalid and any call to them will result the computer's self destruction... well... not quite... but it won't work and put up an annoying error message. To free a DLL you only need the DLL libInstance value you got by calling the LoadLibrary function.
FreeLibrary( libInstance );
That's all... nothing more to do. See you in part two, when we will learn which information we need for a plug-in system and what interfaces we have to create. Any feedback is appreciated, Metron Edit : formating [edited by - Metron on November 27, 2003 9:06:34 AM]

##### Share on other sites
Hello there,

this is quite a good subject so I'll post something about cross-platform compatibility here.
I'll try to annotate the following chapters as well so that the fellow Linux and maybe MacOS X developers around can use this series to learn about interface based plugin systems.

If you read the article and you are not using Windows, you have probably been wondering how to implement the described stuff under your favorite UNIX-based OS :D

There are of course equivalent functions across all OS.
The functions on Windows described earlier were:
HINSTANCE LoadLibrary(char*);void* GetProcAddress( HINSTANCE, char* );void FreeLibrary( HINSTANCE );

Their Linux equivalents are:
void* dlopen(const char* filename, int flag);void* dlsym(void* handle, const char* symbol);int dlclose(void* handle);

As you can see, the parameters are basically the same.
There is an additional 'flag' parameter in the dlopen function.
It can be either RTLD_LAZY or RTLD_NOW which defines the way that external symbols are resolved.
Apart from that there are only type differences: under Windows you have a type HINSTANCE which is replaced with a void* in Linux but it works the same way.

As for most functions you can look up the documentation typing 'man functionname ' (i.e. 'man dlopen') in a console.

Greetings
Marcus

edit: spelIng

[edited by - wi-Z-art on November 27, 2003 11:38:15 AM]

1. 1
2. 2
3. 3
Rutin
22
4. 4
5. 5

• 12
• 19
• 14
• 9
• 9
• ### Forum Statistics

• Total Topics
632929
• Total Posts
3009285
• ### Who's Online (See full list)

There are no registered users currently online

×