DLL と EXE のデバッグ方法

この記事では、ユーザー定義 DLL またはユーザー定義 EXE をデバッグするための2つの手法を紹介します。
- 1つ目の方法は、"debugged“ 値をテキストファイルに書き込むことです。
- 2 つ目の方法は、実行中のプロセスに VisualStudio デバッガーをアタッチすることです。

ここでは、Microsoft Visual Studio Community2017 を使用して示しています。

著者 Michael Humphreys, Sandrine Auriol and Tim Gustafson

Downloads

記事の添付資料

Introduction

この記事は、ユーザ定義 DLL および EXE を Visual Studio での C, C++ または C# でデバッグする方法を紹介します。これらのユーザ定義機能の作成手順については、詳しく説明しません。

テキストファイルを用いたデバッグ方法

ユーザー定義 DLL やユーザー定義 EXE のデバッグ方法の1つに、テキストファイルに"debugged“ 値を書き込む方法があります。以下のユーザー定義の散布関数にデバッグ用の行をいくつか追加してみましょう。

{Zemax} フォルダ \DLL\SurfaceScatter\Lambertian.c

この修正を行った Lambertian_DebugText.cpp というファイルは添付ファイルに添付してあります。

まず、テキストファイルに書き込むために、コードの先頭に以下のライブラリを追加しています。

#include <fstream>
#include <sstream>
#include <iostream>
#include <shlobj.h>
using namespace std;

そして、"DebugBool "パラメータを定義します。

int __declspec(dllexport) APIENTRY UserParamNames(char *data)
    {
    ...
    //debug
    if (i == 3) strcpy(data, "DebugBool");
    return 0;
    }

“DebugBool" パラメータの値に応じて、ファイルが作成され、さらに解析するためにそのファイルに値を書き込むことができます。

     bool debug = data[54] != 0;

     ...

     CHAR my_documents[MAX_PATH];
     fstream debuglog;
     string filepath;
     if (debug)
     {
         SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, my_documents);
         filepath = string(my_documents) + "\\Zemax\\DLL\\SurfaceScatter\\debug.txt";
         debuglog.open(filepath, ios::out | ios::app); // debuglog.close();
         debuglog.precision(12);
     }

     ...

     debuglog << debugged_value << "\t";
     debuglog.close();

このように、テキストファイルに書き込んでデバッグする簡便な方法もあります。

Visual Studio のデバッガー機能を使ったデバッグ方法

DLL や EXE をデバッグ モードでコンパイル

DLL や EXE をデバッグ モードでコンパイルする方法について説明します。例えば、ユーザー定義面 (DLL) をコンパイルしてみましょう。 より詳細については、以下の記事も参照してください。
 "ユーザー定義 DLL をコンパイルする方法".

Debug mode

コンパイルが完了したら、2 つの DLL と PDB ファイルを Projectx64Debug フォルダから {Zemax} フォルダ \DLL\Surfaces フォルダにコピーする必要があります。通常は (DLL をリリース モードで使用する場合)、DLL ファイルのみをコピーしますが、PDB ファイル (Program database ファイル) はプログラムのデバッグ情報を格納するため、ここでは必要になります。

Copy DLL and PDB

DLLが変更されたりコンパイルされるたびに、これらのファイルを Projectx64Debug フォルダから{Zemax} フォルダ \DLL\Surfaces フォルダに手動でコピーする必要があります。

この作業を回避するために、出力フォルダを "Project\x64\Debug" から "{Zemax} フォルダ \DLL\Surfaces" に変更することができます。

C++ の場合 : Visual Studio でソリューション エクスプローラーに移動し、プロジェクトを選択して右クリックし、プロジェクトのプロパティ ページを開き、[構成] (Configuration) タブからで [全般] (General) を選択して、[ターゲット名] (Target Name) を変更します。

C# の場合 : Visual Studio で、Project Preferences > Build > Output directory の順に開いて、設定します。

OpticStudio に戻る

OpticStudio を起動し、ユーザー定義面やユーザーオペランドを選択します。

  • ユーザ定義面の DLL の場合 : 以下の例では、第 2 面をユーザー定義面としていて、デバッグ モードの DLL が使われています。
    User-defined surface in OpticStudio
  • ユーザー定義オペランド UDOC の場合 : UDOC オペランドを評価関数として設定します。必ず [タイムアウト (ms)] (Timeout (ms)) を任意のきわめて大きい値に設定します。これは、Visual Studio で UDOC を実際にデバッグする際に OpticStudio でタイムアウト エラーが生成されないようにするための措置です。
    UDOC in OpticStudio

この時点では、まだ光学系も評価関数も更新しないようにします。更新すると、ユーザ定義面または UDOC が実行されますが、それらのコードにエラーがあると、ブレークポイントを設定する前にクラッシュする可能性があります。

プロセスへのアタッチ

Visual Studio に戻ると、デバッグを開始する準備が整います。ユーザ拡張機能が DLL の場合、デバッガを OpticStudio.exe のプロセスにアタッチします。ユーザ拡張機能が EXE の場合 (ユーザー定義オペランド) は、そのアプリケーション自体のプロセスにアタッチします。

DLL の場合 - OpticStudio へのアタッチ

実行している OpticStudio のプロセスにデバッガをアタッチできます。

以下の [プロセスにアタッチ] (Attach to Process) をクリックします。

Debugger_1.png

ウィンドウが開くので、[選択] (Select) をクリックします。

Debugger_2.png

[ネイティブ] (Native) をクリックします。

Debugger_3.png

[使用可能なプロセス] (Available Processes) の一覧で、適切な OpticStudio プロセスが選択されていることを確認します。1 つの OpticStudio インスタンスのみを開いておくと便利な場合があります。

Debugger_4.png

[アタッチ] (Attach) をクリックします。

EXE の場合 - UDOC への直接アタッチ

UDOC をデバッグするには、OpticStudio にはアタッチせず、UDOC アプリケーション自体にアタッチします。したがって、UDOC コード自体に「一時停止」を設定しておき、実際の実行を一時停止する必要があります。一次停止を設定するには、C# の場合は Console.ReadKey() を、C++ の場合は  system(“pause”) を使用します。
C# のコードの例を以下に挙げます。

Attach to UDOC

ここで評価関数を更新すると、コマンドライン ウィンドウが開き、「デバッガーをアタッチ (Ctrl+Alt+P) した後、キーをどれか押してください」というメッセージが表示されます。:

Update Merit Function

UDOC 自体をデバッガにアタッチします。UDOC の正しいコードを選択していることを確認します。下図の例では、コードが C# で作成されているので、[マネージ コード] (Managed code) を選択しています。

UDOC debugger

UDOC では、評価関数を更新する必要があるたびに、プロセスをアタッチする必要がある点に注意してください。

ブレークポイントの設定

次に、渡される値をプロセスを止めて調べるために、DLL や EXE のコードにブレークポイントをいくつか設定します。

Breakpoint

DLL/EXE の実行

OpticStudio では、ユーザー定義面をクリックするか、UDOC オペランドを設定した状態で Merit Function を更新すると、DLL または EXE が実行され、デバッガが起動されます。Visual Studio に戻ると、ブレークポイントに黄色の矢印が表示されます。これは、次に実行されるコードを示しています。

[デバッグ] (Debug) → [ウィンドウ] (Window) → [ローカル] (Locals) ウィンドウに、DLL と OpticStudio の間で受け渡される値が表示されます。このウィンドウにより、OpticStudio と DLL の間で、2 種類のデータ構造体としてユーザー データ (UD) と固定データ (FD) が受け渡されていることがわかります。

Run DLL

ユーザー データ UD

この UD には、面の頂点に接する平面上の光線位置 x、y、z (実際の面について DLL で計算して返された値)、光線の方向余弦 l、m、n、この面の法線 ln、mn、nn (計算して返された値) のほか、屈折率、透過率、光路長などのデータを収めています。

UD

固定データ FD

Fixed Data FD

FD には、おもに DLL では変更できないデータを収めています。このようなデータとして、レンズ データ エディタに記述された面データ (曲率半径、コーニック定数、各種パラメータなど)、光線の波長、偏光の状態、Type パラメータと Numb パラメータ (OpticStudio から DLL を呼び出して取得するデータを示します) などがあります。

FD

たとえば、上図では FD の n2 のデータとして N_BK7 の屈折率が OpticStudio から DLL に渡されていることがわかります。

デバッガの停止

デバッガを終了するには、赤色の正方形をクリックします。

Stop debugger

リリース モードでの DLL/EXE の頒布

DLL/EXE のデバッグが完了した後、必ず構成をデバッグからリリースに戻し、ソリューションを再コンパイルします。デバッグ構成のライブラリは再頒布できませんが、リリース構成のライブラリは再頒布が可能です。

参考文献

KA-01636

この記事は役に立ちましたか?
2人中1人がこの記事が役に立ったと言っています

コメント

0件のコメント

記事コメントは受け付けていません。