Загрузка DLL 32 или 64 бит from.Net управляемый код

У меня есть неуправляемая DLL (scilexer.dll редактора кода Scintilla, используемого Scintilla.Net от CodePlex), который загружается из управляемого приложения через Scintilla.Net компонент. Управляемое приложение windows работает без проблем как в 32, так и в 64-битных средах, но мне нужно создать различные установки, которые используют 64 или 32 scilexer.файл DLL.

есть ли способ распространять обе библиотеки DLL в 32 и 64-битном формате, чтобы загрузчик DLL .Net framework загружает неуправляемую DLL в 32 или 64-разрядном формате в зависимости от некоторых .опция config или какая-то" магия имени пути"?

5 ответов


P / Invoke использует LoadLibrary для загрузки DLL, и если библиотека уже загружена с заданным именем, LoadLibrary вернет его. Поэтому, если вы можете дать обеим версиям DLL одно и то же имя, но поместить их в разные каталоги, вы можете сделать что-то подобное только один раз перед первым вызовом функции из scilexer.dll, без необходимости дублировать ваши объявления extern:

    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 + ".");

к сожалению, я ничего не знаю об этой конкретной DLL. Однако, когда вы делаете P/Invoke самостоятельно, и вы можете справиться с небольшим дублированием, можно создать один прокси для каждой платформы.

например, предположим, что у вас есть следующий интерфейс, который должен быть реализован либо 32, либо 64-битной DLL:

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

вы создаете прокси:

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);
    }
}

и

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);
    }
}

и, наконец, сделать завод, который выбирает правильный для вас:

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;
    }
}

поскольку DLL загружаются лениво при первом вызове, это действительно работает, несмотря на то, что каждая платформа может загружать только версию, которая является родной для нее. См.в этой статье для более подробного объяснения.


лучшее, что я придумал следующее:

  • распространять мое приложение с двумя DLL с именем 64 или 32
  • в основной код запуска включите следующее:
    
    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");
        }
    }

вы можете поместить dll в system32. 32 бит в syswow64 и 64 бит в реальной system32. Для 32-битного приложения, когда thay access system32 они перенаправляются на Syswow64.

вы можете создать запись в реестре. Программный ключ имеет подраздел с именем Wow6432Node, который 32-разрядное приложение видит как программный ключ.

вот что установщик powershell делает.


неуправляемые библиотеки DLL могут быть установлены в GAC бок о бок со своими управляемыми аналогами. в этой статье должны объяснить, как это работает.