Question

I have a unmanaged DLL (the scilexer.dll of Scintilla code editor, used by Scintilla.Net from CodePlex) that is loaded from a managed application trough the Scintilla.Net component. The windows managed application runs without problem on both 32 and 64 bit environments, but I need to create different installations that uses the 64 or the 32 scilexer.dll.

Is there a way to distribute both DLLs in 32 and 64 bit format so that the DLL loader of the .Net framework loads the unmanaged DLL in the 32 or 64 bit format depending on some .config option or some "path name magic" stuff?

Was it helpful?

Solution

P/Invoke uses LoadLibrary to load DLLs, and if there is already a library loaded with a given name, LoadLibrary will return it. So if you can give both versions of the DLL the same name, but put them in different directories, you can do something like this just once before your first call to a function from scilexer.dll, without needing to duplicate your extern declarations:

    string platform = IntPtr.Size == 4 ? "x86" : "x64";
    string dll = installDir + @"\lib-" + platform + @"\scilexer.dll";
    if (LoadLibrary(dll) == IntPtr.Zero)
        throw new IOException("Unable to load " + dll + ".");

OTHER TIPS

Unfortunately, I don't know anything about this particular DLL. However, when you do the P/Invoke yourself, and you can cope with a little duplication, it's possible to create one proxy for each platform.

For instance, suppose that you have the following interface, that should be implemented by either a 32 or 64 bit DLL:

public interface ICodec {
    int Decode(IntPtr input, IntPtr output, long inputLength);
}

You create the proxies:

public class CodecX86 : ICodec {
    private const string dllFileName = @"Codec.x86.dll";

    [DllImport(dllFileName)]
    static extern int decode(IntPtr input, IntPtr output, long inputLength);

    public int Decode(IntPtr input, IntPtr output, long inputLength) {
        return decode(input, output, inputLength);
    }
}

and

public class CodecX64 : ICodec {
    private const string dllFileName = @"Codec.x64.dll";

    [DllImport(dllFileName)]
    static extern int decode(IntPtr input, IntPtr output, long inputLength);

    public int Decode(IntPtr input, IntPtr output, long inputLength) {
        return decode(input, output, inputLength);
    }
}

And finally make a factory that picks the right one for you:

public class CodecFactory {
    ICodec instance = null;

    public ICodec GetCodec() {
        if (instance == null) {
            if (IntPtr.Size == 4) {
                instance = new CodecX86();
            } else if (IntPtr.Size == 8) {
                instance = new CodecX64();
            } else {
                throw new NotSupportedException("Unknown platform");
            }
        }
        return instance;
    }
}

As the DLLs are loaded lazily the first time they are being invoked, this actually works, despite each platform only being able to load the version that is native to it. See this article for a more detailed explanation.

The best I've come up with is the following:

  • Distribute my application with two DLLs named 64 or 32
  • In the main startup code include the following:
    
    File.Delete(Application.StartupPath + @"\scilexer.dll");
    {
      // Check for 64 bit and copy the proper scilexer dll
        if (IntPtr.Size == 4)
        {
          File.Copy(Application.StartupPath + @"\scilexer32.dll",
            Application.StartupPath + @"\scilexer.dll");
        }
        else
        {
          File.Copy(Application.StartupPath + @"\scilexer64.dll",
            Application.StartupPath + @"\scilexer.dll");
        }
    }

You can put the dll in system32. The 32 bit in syswow64 and the 64 bit in the real system32. For 32 bit application, when thay access system32 they are redirected to Syswow64.

You can create an entry in the registry. The software key has a subkey named Wow6432Node that 32 bit application see as the software key.

Here is what powershell installer does.

Unmanaged dlls can be installed into the GAC side-by-side with their managed counterparts. This article should explain how it works.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top