Introduction
Since I started working in .NET, I was able to load Win32 libraries dynamically in an application and call its exported functions. When several libraries expose the same functions, it is possible for an application to load and work with them dynamically. They are not required to exist when the application is run. This is the basic functionality of legacy plug-ins.
When .NET came out, the way of working with these libraries changed and new ways of working the plug-in concept also showed up. Although these new ways provide many advantages, there are lots of pre-existing plug-ins that could improve new .NET applications.
Background
For some time now, I've been working on a way to load these same Win32 plug-ins in .NET (C#, specifically). This has lead to a number of trials and and many failures, but I finally came with a fully managed Win32 plug-in loader for .NET applications.
In the past, in the days before I learned C#, it was possible to load dynamic libraries using Windows API functions LoadLibrary
, GetProcAddress
, and FreeLibrary
. However, to my surprise, when I tried to load legacy libraries within .NET with some code derived from what I used to do using Delphi, I found out it would not be that simple. After some time, I got tired of trying (even using unsafe
) and posted a question on a MS newsgroup. There, I came to know that it was really not possible. The problem is: I still wanted a solution.
DllImportAttribute
What we first learn about using Win32 libraries in .NET is to use the DllImportAttribute
. It allows us to declare a static method having its implementation in a Win32 library. The example below shows how to load the MessageBeep
function from Windows API:
[DllImport ("user32.dll")]
public extern static void MessageBeep(int value);
This is the simplest thing we could do, but what happens when we have to load several libraries with the very same methods? We could create several different new classes, one for each plug-in library we have to handle. This is not a very good idea because we'll have to create a new class for each new plug-in to be used, and this is not a simple task.
On the other hand, we can create a class for each library. The trick involves System.Reflection.Emit
namespace. It could be a little difficult, at first, for those who are unfamiliar with Reflection, to understand the steps to build new classes dynamically, but it will result in a very large source code and will also consume lots of resources from the machine every time a library requires a new class. I'm not wasting my time explaining how this works, sorry.
Legacy for the legacy
Then it came to me that I could still know only one library to call the plug-ins. We are not allowed to convert and call the function pointer returned by GetProcAddress
as, for example, a .NET delegate. Although, we can still use the pointer returned by LoadLibrary
. So, we could create another Win32 library to be imported with the following code:
[DllImport ("user32_stub.dll")]
public extern static void MessageBeep(IntPtr lib, int value);
This is where the trick lies. We have a well-known DLL but it isn't the plug-in call yet. Notice the first parameter in this method; it could be anything, but we'll use the return value of the LoadLibrary
function as its value. Once we can't call the dynamic function directly, this new library will perform the GetProcAddress
call, convert the returned pointer, and call the desired function. It works as a front-end just to call any plug-in. The front-end looks like a plug-in library, but every exported function has an additional IntPtr
parameter. It's very important to remember that every method of the plug-in libraries must have a correspondent in this front-end in order to be used.
I'm not extending myself to explain how this process works in practice, since I wrote another article about it previously. This article can be found here. The important thing to notice is that its overhead is smaller than creating new classes every time the application runs.
A solution with managed code
This need for another legacy library to use Win32 plug-ins always annoyed me a little. Although I tried to move ahead, I was always looking for some new idea to better solve this question.
In the past few days, I found another article on CodeProject (Execute Native Code from .NET, by Maxim Alekseikin) which gave a new idea to try. In the article, the author explained how to embed native code in a .NET application (as a constant byte array) and execute it using the Marshal
class. So far I had a limited view of the capabilities of that class and, to me, every new idea was worth trying.
Using this new knowledge, I derived the author's sample to use a few extra types and steps to finally convert the address returned by GetProcAddress
into a Delegate. Also, to reduce the code and type casting required for the example to work, I began to use Generics from .NET Framework 2.0.
The new sample involves Generics, MarshalAsAttribute
, and a new pair structure-delegate (one for each function exported by plug-in libraries), and effectively allowed me to cast the function pointer (passing through a single-IntPtr
structure and a free-form memory reference) to the desired Delegate. This combination allowed me to code it simple, easy to understand, and use it quickly.
Points of interest
Still, I'm not sure if it's possible to cast the pointer conversion (from GetProcAddress
) to a delegate using Delphi 8 the same way we used to, once they tried to keep full compatibility with previous versions. My first supposition is no, but if anyone has tested and made it work, share it too.
Also, I haven't had the time to test the code under .NET 1.0 or 1.1, so it may not work as expected, but considering the framework hasn't changed in this part, maybe it will work. I'll leave that for someone else to do the test.