views:

165

answers:

2

Hi.

First, I know that it doesn't make sense to compare the dllimport attribute and the getProcAddress function directly. Rather, I am interested in comparing two pieces of code, that achieve basically the same thing - calling a function in a dll - by either importing the function with the dllimport attribute or with the getProcAddress function. Specifically, I am writing a C# application that uses some function in a dll that I have written. At first I accessed my dll function with the following piece of code:

class DllAccess
{
    [DllImport("kernel32.dll", SetLastError = true)]
    private extern IntPtr LoadLibrary(String DllName);

    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    private delegate Bool BarType(Byte arg); // return value indicates whether function call went well or not.

    Bool Bar(Byte arg)
    {
        Bool ok = false;
        IntPtr pDll= LoadLibrary("foo.dll");
        if (pDll != IntPtr.Zero)
        {
            IntPtr pfunc = GetProcAddress(pDll, "bar");
            if (pFunc != IntPtr.Zero)
            {
                BarType bar = (BarType)Marshal.GetDelegateForFunctionPointer(pFunc, typeof(BarType));
                ok = bar(arg);
            }
            FreeLibrary(pDll);
        }
        return ok;
    }
}

However, I later needed to get at the lastError value, if it had been set during the dll call, so I changed my code into this:

class DllAccess
{
    [DllImport("foo.dll", EntryPoint = "bar", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
    private extern Bool DllBar(Byte arg); // return value indicates whether function call went well or not.

    Bool Bar(Byte arg)
    {
        return DllBar(arg);
    }
}

This is of course much tidier, and as mentioned, it sets the lastError code. Obviously, my first piece of code gives me the possibility of changing dll and function call at runtime, but at the moment this is not required. So my question is: Are there any reasons for using the first formulation, if I am certain, that I will not be using another dll or another function?

+4  A: 

The only real advantages of using GetProcAddress are that you can unload the DLL manually as well as call a function, and that you can change the naming easily at runtime.

However, the second option provides you with a huge number of benefits. In addition to being "tidier", it also handles much of the marshaling of data types for you - which becomes very important with certain APIs.

That being said, if you do the method you have listed as first, you should make sure to unload everything, as well. Right now, you're basically leaking addresses each time you call Bar()... For details, look at FreeLibrary.

Reed Copsey
Thank you for your answer. In my code, I actually loaded the library in the constructor, freed the library in the destructor, and used the whole thing as a singleton, since I didn't know if it would cause trouble to load the library more than once. In the interest of correctness I have edited my post to also free the library.
Boris
@Boris: `LoadLibrary` and `FreeLibrary` do reference counting, so multiple calls tend to work out ok.
Ben Voigt
@Reed: What do you mean by "leaking addresses"? The DLL is loaded only once, only one copy of the function exists in memory, and the delegate is garbage collected.
Ben Voigt
@Ben: It actually keeps extra pointer counts in memory, though - it's not a big deal, since the library's loaded 1 time only due to reference counting, but you do actually leak a pointer, and it's probably better to unload the library if you're not going to keep using it anyways...
Reed Copsey
+2  A: 

Probably the biggest advantage of GetProcAddress is that it lets you control the search path of the DLL. For example, you could load either 32-bit or 64-bit version of a native DLL automatically. With DllImportAttribute, this isn't possible.

Ben Voigt
Ben: Just an FYI - You can do this with [DllImport] by having the library in a separate path, and changing the search paths at runtime.
Reed Copsey
You mean messing with the PATH environment variable? Not recommended. http://blogs.msdn.com/b/oldnewthing/archive/2008/12/11/9193695.aspx
Ben Voigt