zoukankan      html  css  js  c++  java
  • C#からネイティブDLLを呼び出す場合のVSからのデバッグのジレンマを解決する

     

    C#を使う最大のメリットって、やっぱり、Visual Studioですよね!」って自信を持って言いたいですね。

    という心境ではあるんですが、私の仕事はどっちかというとC++よりなので、どうしても、DllImportはお友達という側面があります。そうすると、プログラム実行時に、

    AnyCPUなアセンブリ.exe
    ネイティブC++.dll

    みたいな感じになって、要は、AnyCPUなアセンブリがネイティブC++ちゃんを呼び出す構図になるんですが、この構成、64-bitの環境で開発をしていたりすると相当なジレンマを抱えることになります。

    普通に実行する場合には、x64環境なので、「ネイティブC++.dll」さんは、64-bit版を配置しておくべきなんですが、VS上からデバッグしようとすると、win32(32-bit版)を置いておかないと行けなかったり、あるいは、「ネイティブC++.dll」さんのデバッグ版は激遅なので、デバッグ中でも普通はリリース版を置いておきたかったりと、様々な面倒なシチュエーションに出くわすことになります。

    で、これを解決する方法を考えたよという話です。
    簡単に言うと、

    AnyCPUなアセンブリ.exe
    win32/
      ネイティブC++.dll
    x64/
      ネイティブC++.dll

    というディレクトリ構成にしてしまえという。「AnyCPUなアセンブリ.exe」は、賢いので、自分が実行されている環境に応じて、どっちをロードするか見てくれるという。

    で、どうするかというと、次みたいなコードをアプリに取り込んでしまえという。
    これは、MainWindow.xaml.csとかの例ですが、もっと早い段階がよければ、そこでやっても良いですね:

    static MainWindow()
    {
      SetDllDirectory("");
    #if DEBUG
      if (setDllLocation(true))
        return;
    #endif
      setDllLocation(false);
    }
    
    /// <summary>
    /// Controlling DLL directory which native DLLs are loaded from.
    /// </summary>
    /// <param name="debug">Whether this is debug mode or not.</param>
    /// <returns><c>true</c> if DLL directory is correctly set; otherwise <c>false</c>.</returns>
    static bool setDllLocation(bool debug)
    {
      var appDir = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
      if (debug) appDir = Path.Combine(appDir, "debug");
      var dllDir = Path.Combine(appDir, IntPtr.Size == 8 ? "x64" : "win32");
      if (Directory.Exists(dllDir))
      {
        Debug.WriteLine(string.Format("Set DLL Location ({0}): {1}", debug ? "Debug" : "Release", dllDir));
        SetDllDirectory(dllDir);
        return true;
      }
      return false;
    }
    
    [DllImport("Kernel32.dll")]
    static extern bool SetDllDirectory(string lpPathName);
    

    やってることの内容としては、 SetDllDirectory APIを呼び出して、DLLをロードするディレクトリを事前に変更しておこうと。
    C++だと、delayloadがらみを調整して同じような事が出来ますが、C#でのDllImportは完全に実行時にバインディングを解決することになるので、かなりこういう芸当がやりやすいです。

    で、上のコードにはオマケがあって、デバッグ版では、さらに、

    AnyCPUなアセンブリ.exe
    debug/
      win32/
        ネイティブC++.dll
      x64/
        ネイティブC++.dll

    みたいなレイアウトにしておけば、デバッグ版のDLLを見つけてロードしてくれると。
    いずれにしても、デバッグ時にDLLをコピーしたり移動したりの右往左往がかなり軽減されるという意味では開発が楽になると思います。

  • 相关阅读:
    cordova的安装与配置
    JavaScript-string
    JavaScript-Number
    android-适配器
    网络操作-转码(乱码情况处理)
    网络操作-请求优先级
    Android读取权限
    I/O-<File区别>
    I/O-<File实例>
    I/O-<文件读写、输出>
  • 原文地址:https://www.cnblogs.com/xpvincent/p/9903416.html
Copyright © 2011-2022 走看看