この記事では、Visual Studio でユーザー定義 DLL をコンパイルする方法を紹介します。ユーザー定義 DLL の概要についても簡単に触れます。このチュートリアルは、Visual Studio Community 2017 バージョン 15.9 を使用して作成していますが、それより前のバージョンでも機能します。バージョン間の相違点も示します。利用可能な他のコンパイラについても述べます。新規 DLL の作成方法については説明していないことをご承知ください。
著者 Alexandra Culler、Michael Humphreys、Sandrine Auriol
序論
OpticStudio の Professional エディションと Premium エディションでは、C または C++ によるプログラムを通じて光学系に独自の光学部品をリンクできます。どのようなコンパイラでも C/C++ のコードをコンパイルできますが、最も容易に入手できるコンパイラとして Visual Studio があります。この記事では、DLL をコンパイルする方法を、段階を追って説明します。
ユーザー定義 DLL の概要
OpticStudio は、ユーザー定義 DLL を使用してカスタマイズできます。
- シーケンシャル モードでは、光学材料間の境界を面で定義します。面は、屈折性、反射性、回折性、または屈折率特性とすることができます。OpticStudio は、65 を超える各種面タイプに対応しています。このような面タイプとして、多項式面やバイコーニック ゼルニケ面など、きわめて一般化した面の形状もあります。それでも、固有のニーズに合わせてカスタマイズした面が必要になる状況も少なくありません。ユーザー定義面がきわめて効果的で機能的となるのは、そのような場合です。OpticStudio には、そのような機能とのインターフェイスが用意されているからです。
- ノンシーケンシャル モードでは、材料間の境界をオブジェクトで定義します。オブジェクトは、所定の材料で構成された形状を表します。オブジェクトには、光を回折または散乱するフェイスを設定できます。光が散乱する材料を使用することや、オブジェクトを光源とすることも可能です。OpticStudio には、このような操作をすべて実現する、組み込みのオブジェクトとプロパティが用意されています。ノンシーケンシャル モードでは、ユーザー定義オブジェクト、GRIN プロファイル、回折アルゴリズム、面散乱アルゴリズム、バルク散乱アルゴリズム、ユーザー定義光源のすべてを、独立した DLL でカスタマイズできます。
64 ビットの要件
以前の OpticStudio は、32 ビットまたは 64 ビットのいずれかのアプリケーションとしてリリースされていました。その結果、インストールした OpticStudio のバージョンがどちらであるかに応じて、32 ビットまたは 64 ビットの DLL が生成されていました。しかし、現在の OpticStudio は 64 ビット アプリケーションのみで提供されています。DLL の使用時に下図のようなエラー メッセージが表示される場合は、この記事で紹介する手順に従い、ソース コードを再コンパイルする必要があります。
注 : Visual Studio の旧バージョンを使用している場合、この記事の手順を実行するには、64 ビット用コンパイル パッケージ (Windows SDK 7.1) のダウンロードが別途必要になることがあります。ダウンロードの完了後、[ツール] (Tools) → [オプション] (Options) → [環境] (Environment) → [プロジェクトとソリューション] (Projects and Solutions) に移動します。表示されたウィンドウで [ビルド構成の詳細を表示] (Show advanced build configurations) を有効化し、次のように設定されていることを確認します。
([ツール] (Tools) → [オプション] (Options) で表示されるダイアログは、[プロジェクト プロパティ] (Project Properties) ダイアログとは異なります。)
DLL のコンパイル
全般的な設定
ダイナミック リンク ライブラリ (DLL) ファイルは、Visual Studio のプロジェクトで得られる出力タイプの一種です。DLL を作成するために、まず親コードを格納するプロジェクト空間を作成します。
Visual Studio で [ファイル] (File) → [新規] (New) → [プロジェクト] (Project) に移動します。
プロジェクト タイプとして Windows デスクトップ ウィザードを選択します。このタイプは、Visual C++ のオプションに表示されます。
つづいて、アプリケーション タイプとして [ダイナミック リンク ライブラリ (.dll)] (Dynamic Link Library (.dll)) を選択します。
プロジェクトを作成した後の最初の手順は、ビルド タイプの変更です。[ビルド] (Build) → [構成マネージャー ...] (Configuration Manager...) に移動します。
構成マネージャーでソリューションの構成を [リリース] (Release) に設定して、コードの実行によって DLL 出力が得られるようにします。プラットフォームは [x64] に設定する必要があります。これは、コードに 64 ビットのシステムとアプリケーションとの互換性を確保することを意味します。
次に、ソース ファイルを追加します。ソース ファイルは CPP タイプとする必要があるので、[新しい項目 ...] (New Item...) を選択して C++ ファイルを指定します。
{Zemax}\DLL フォルダには、ユーザー定義コード作成の出発点となるサンプル ファイルがいくつか保存されています。これらのサンプル ファイルのいずれかを使用するには、新規作成した C++ ソース ファイルに、そのサンプル ファイルのコードをコピーします。
サンプル ファイルを読み込んだので、プロジェクト設定の所要箇所を変更する必要があります。プロジェクト名を右クリックして [プロパティ] (Properties) を選択します。
[構成プロパティ] (Configuration Properties) → [全般] (General) で、下図のように [構成の種類] (Configuration Type) が [ダイナミック ライブラリ (.dll)] (Dynamic Library (.dll)) に設定されていることを確認します。通常は、[文字セット] (Character Set) は [マルチバイト文字セットを使用する] (Use Multi-Byte Character Set) に設定します。
注 : この記事の冒頭で追加のダウンロードを必要とした Visual Studio の旧バージョンでは、[プラットフォーム ツールセット] (Platform Toolset) を [Windows7.1SDK] に設定する必要があります。
続いて [構成プロパティ] (Configuration Properties) → [C/C++] → [コード生成] (Code Generation) で [ランタイム ライブラリ] (Runtime Library) を選択します。通常は、[マルチスレッド (/MT)] (Multi-threaded (/MT)) または [マルチスレッド DLL (/MD)] (Multi-threaded DLL (/MD)) の使用をお勧めします。
これらのどちらを選ぶかは少々複雑ですが、ほとんどの場合、互換性と使いやすさとのバランスで判断することになります。他のライブラリとのインターフェイスを使用しないユーザー定義 DLL であれば、マルチスレッド ランタイム ライブラリを使用する方が得策です。その DLL を使用するコンピュータに C++ の再頒布可能パッケージをインストールする必要がないからです。一方、DLL で他のライブラリを使用するのであれば、同種のランタイム ライブラリを使用する必要があります。その場合の相手側ライブラリは、ほぼ必ずと言ってよいほどマルチスレッド DLL ランタイムです。
他のサードパーティー ライブラリを使用しない簡潔な DLL の場合は、マルチスレッド ランタイムの選択が最良であるといえます。
以上の設定が完了したところで、[OK] をクリックして [プロパティ] (Properties) ダイアログを閉じます。
コードのエラーの確認
ここでは、親コードが、すべてのファイルを認識できることを確認します。DLL がユーザー定義面で、そのソース ファイルを {Zemax}\DLL\Surfaces フォルダ以外に保存していると、ヘッダー ファイル "usersurf.h" が認識されません (下図で赤下線が表示されたファイル)。
この問題を解決するには、{Zemax}\DLL\Surfaces の "usersurf.h" をコピーし、ソース コードが保存されているディレクトリに貼り付けます。新たにコピーしたヘッダー ファイルを読み込みます。そのためには、[ヘッダー ファイル] (Header Files) を右クリックして、目的の既存のコードをインポートします。
ヘッダー ファイルを適切なディレクトリに保存すれば、コードに赤下線は表示されなくなります。認識されないファイルがあると、DLL をコンパイルできないことがあります。コンパイルできたとしても、期待した動作が得られないことが考えられます。
C++ コンパイラの使用
Zemax が提供するサンプル ファイルの大半は、C 言語で作成されています。Visual Studio は C++ のコンパイラであるため、サンプル ファイルを適切にコンパイルするには、いくつかの変更が必要になります。
コードの冒頭にある初期化関数が "extern "C" {}" で囲まれていない場合は、そのように囲んで記述します。さらに、行 "BOOL WINAPI DllMain" がコメント アウトされていることを確認します。
通常、C++ コンパイラでは、各関数が一意の識別子を持つように、関数名が内部的に変更されます。このように関数名が変更されていると、OpticStudio では DLL を実行できなくなります。これは、固有の関数名 (UserDefinedSurface、UserObjectDefinition など) を探し出そうとするからです。上記のようにコードを変更することで、C コードに記述された関数名をそのまま使用すること、それによって発生する可能性があるエラーをすべて無視することを、コンパイラに指定できます。
同様に、C と C++ との軽微な差異によって発生する警告も抑止されるようにする必要があります。そのような警告の例として、次のようなものがあります。
C4996: ‘srtcpy’: This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS.
コンパイル中に発生する警告が上記のみの場合は、次のコードを使用することで、この互換性の問題を回避できます。
#pragma warning ( disable : 4996 )
この行を記述すると、C 言語と C++ 言語との総合的な互換性を維持しながら、コンピュータ/オペレーティング システム固有の機能がコンパイラから得られるようになります。
ソリューションのリビルド
[ビルド] (Build) → [ソリューションのリビルド] (Rebuild Solution) を選択するか、キーボードの Ctrl + F5 を押すことでコードをコンパイルします。ビルドが正常に終了すると、以下の内容が出力されます。
目的の DLL は、ソリューション フォルダに保存されています。プロジェクト "My_Surface" の場合であれば、DLL は {プロジェクト ディレクトリ}\My_Surface\x64\Release にあります。
この DLL を適切な {Zemax}\DLL\ フォルダに保存します。これで、その DLL を OpticStudio で使用できるようになります。
コンパイラ
以下のバージョンの Visual Studio で OpticStudio のユーザー定義 DLL をコンパイルできることが確認されています。
- 2005, 2008
- Express 2010, Express 2012
- Community 2017, Community 2019. 使用条件については、Microsoft のウェブ サイトをご確認ください。
Visual Studio 以外でも、Windows のマルチスレッド DLL プロジェクトを作成できるものであれば、あらゆる 64 ビット C コンパイラを使用できます。使用できるコンパイラは膨大な数に上ります。Visual Studio 以外のコンパイラを使用して問題が発生した場合は、そのプログラムのテクニカル サポートに、「空のマルチスレッド Win32 DLL プロジェクトの作成方法」を問い合わせることをお勧めします。
独自の面や光源などを DLL で作成して OpticStudio で使用できるようにする機能は、光学系のより正確なモデルの構築を実現する高機能なツールです。
参考文献
サンプル コードで使用されているプログラミング コマンドを理解するには、ウェブ サイト http://www.cplusplus.com/reference/ をご覧ください。
KA-01787
コメント
サインインしてコメントを残してください。