Solved

テキストファイルからデータを読み取り、パースするDLL(C++)

  • 31 July 2023
  • 1 reply
  • 130 views

Userlevel 3
Badge +1

このポストでは、テキストファイルから値を読み取るりパースするためのDLLのC++のサンプルコードを公開します。

このポストは主に以下の記事の補足ですが、C++スタイルでこのコードを作成する方法について議論します。

ユーザー定義面に静的データ ファイルを読み取る方法 – 日本語ヘルプ (zemax.com)

icon

Best answer by Takashi Matsumoto 31 July 2023, 17:21

View original

1 reply

Userlevel 3
Badge +1

添付ファイルの中に、サンプルコードがあります。このコードは、以下のポストに示されているのと同じことを行うためのコードですが、違いは回折効率データがテキストファイルから読み込まれる点です。

Simulate 2D diffraction grating using customized diffractive DLL | Zemax Community

このサンプルコードについて、1行1行見ていきます。

 

最初に行うことは、すべての関数の外部で宣言されるグローバル変数を定義することです。この記事 でも書かれている通り、OpticStudioでの光線追跡中、DLLは何度も呼び出されます。グローバル変数であれば内部の値は変更されないので、DLLは常に異なるスレッドで呼び出されても同じデータを見ることができます。今回の例では、OpticStudioがDLLを最初に呼び出したときに、テキストファイルからデータを読み込み、このグローバル変数に保存するようにします。そうすれば、その後テキストファイルを読み込む必要はなく、グローバル変数に保存されたデータを読み込むだけでよいからです。

 

C++では、ベクトル<>が必要なデータを処理できないと思われる場合を除き、ポインタを使用しないことをお勧めします。今回は以下の様に、回折効率の値を格納するためのRdataとTdataの2つのdoubleベクトルを定義し、同様にx方向とy方向の回折次数を保存するための2つの整数を定義しました。

 

なお、ベクトルを使用するためには、以下の標準ライブラリ(STL)をIncludeする必要がある点に注意してください。

 

DllMain()関数の内部では、以下の様にまずテキストファイルからデータを読み込んで解析するための変数を定義します。

 

まずul_reason_for_allの値をチェックします。この変数は4つの値をとりますが、ここではDLL_PROCESS_ATTACHの場合のみを使用します。この値は、OpticStudioが初めてこのDLLを呼び出すときにのみ真になります。DLL_PROCESS_DETACHは、OpticStudioでDLLを削除するとき、またはOpticStudioを閉じるときに呼び出されることに注意してください。

 

では、DLL_PROCESS_ATTACHの場合、テキストファイルの読み込みはどのようになるのか確認します。下の図の39~48行目の部分でテキストファイルを開くための部分です。本例では2D_grating_efficiency_data.txtとしていますが、必要に応じて変更します。

 

テキストファイルのオープンに失敗すると、エラーが報告され、DLL は OpticStudio に FALSE を返します。以下は、エラーがどのように表示されるかを示しています。左側は DLL が返すメッセージです。右側は DLL が FALSE を返した場合に OpticStudio が返すメッセージです。

 

データを解析する方法はたくさんありますが、ここではstringstreamを使った方法を紹介します。以下の51行目から53行目までが、テキストファイルの新しい行を読み込んだ際に3つの値としてデータを取得します。これらの行の値がファイル中では空白で区切られていることを確認してください。そうすれば、55行目に示すように、データを単純にパースすることができます。57~62行目はデータの妥当性チェックを行っています。63-64行目では、値が奇数整数であることを確認しています。これは例で、実際にパースする値やその扱いについてのDLLのフォーマットをどうするかはユーザーが決める必要があります。

 

ベクトルにデータを保存する前に、ベクトルのサイズを定義することが重要で、これを怠るとエラーが発生します。

 

72行目から96行目にかけて、各データを読み込むためのforループで、num_nx*num_ny行のデータを1行ずつ読み込みます。

75行目と77行目は、ループの係数をxとyの対応する順番の係数に変更しています。

78-79行目では、すべてのデータが読み込まれる前にファイルの末尾に達したかどうかをチェックしています。もしファイルの末尾に達した場合、エラーを返します。

82行目から84行目までは、前述の「3つの値」です。

86~95行目は、反射と透過のための効率データをパースし、そのパースが成功したことを確認し、その値をベクトルに保存します。

97行目は、開いたテキストファイルを閉じます。

 

そしてメインコードでは、以下のようにグローバル変数のRdataとTdataのデータを呼びだして使うことになります。

 

なお、このポストではベクトルの使い方についてはあまり触れませんでしたが、検索エンジンを使えばたくさんの参考となる情報を参照できます。例えば、初めてベクトルを使う人に向けては、以下のようなページがよい参考になります。

 

C++ Tutorial: A Beginner's Guide to std::vector, Part 1 | CodeGuru

 

また、サンプルシステムとサンプルテキストファイルも添付します

サンプルのテキストファイルは、コード中で定義してあるようにZemaxフォルダ\ DLL\Diffractiveフォルダの中に入れて使用してください。

 

 

Reply