32- или 64-битная загрузка DLL из управляемого кода .Net - PullRequest
6 голосов
/ 18 декабря 2008

У меня есть неуправляемая 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 ]

5 голосов
/ 17 марта 2009

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

    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 + ".");
4 голосов
/ 31 января 2009

К сожалению, я ничего не знаю об этой конкретной 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 загружаются лениво при первом вызове, это на самом деле работает, несмотря на то, что каждая платформа может загружать только ту версию, которая ей присущи. См. эту статью для более подробного объяснения.

2 голосов
/ 18 декабря 2008

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

  • Распределите мое приложение с двумя библиотеками 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");
        }
    }
1 голос
/ 18 декабря 2008

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

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

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

0 голосов
/ 18 декабря 2008

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

...