代码之家  ›  专栏  ›  技术社区  ›  massimogentilini

从.Net托管代码加载32或64位DLL

  •  6
  • massimogentilini  · 技术社区  · 16 年前

    我有一个非托管DLL(斯金特拉代码编辑器的scilexer.DLL,由来自 CodePlex

    是否有方法以32位和64位格式分发DLL,以便.Net framework的DLL加载程序根据某些.config选项或某些“路径名魔术”内容以32位或64位格式加载非托管DLL?

    5 回复  |  直到 16 年前
        1
  •  5
  •   user78842 user78842    15 年前

    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 + ".");
    
        2
  •  4
  •   SteinNorheim    15 年前

    不幸的是,我对这个特定的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在第一次被调用时是延迟加载的,这实际上是可行的,尽管每个平台只能加载其本机版本。看见 this article 以获取更详细的解释。

        3
  •  2
  •   massimogentilini    16 年前

    我想到的最好的办法是:

    • 在主启动代码中,包括以下内容:
        
        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");
            }
        }
    
        4
  •  1
  •   Igal Serban    16 年前

    您可以将dll放入system32中。syswow64中的32位和实际system32中的64位。对于32位应用程序,当他们访问system32时,他们被重定向到Syswow64。

    这是什么 powershell installer does .

        5
  •  0
  •   Joel Lucsy    16 年前

    This article 应该解释它是如何工作的。

    推荐文章