LabVIEWで使用するためのMicrosoft Visual C++を使用したDLLの構築

更新しました May 30, 2021

環境

ソフトウェア

  • LabVIEW

その他

  • Microsoft Visual Studio

MicrosoftのVisualC++(MSVC)統合開発環境(IDE)は、プログラマーがこれを使用したことがない場合、どうしたらよいか分からない可能性があります。このドキュメントは、LabVIEWで使用するためにDLLをコンパイルしたい人を支援することを目的としています。

:このドキュメントはMSVC2010を使用して作成されました

DLLプロジェクトを作成する

Microsoftのチュートリアルの手順に従って、C ++ DLLを作成します。 Walkthrough: Create and use your own Dynamic Link Library (C++)
  1. Visual Studioで、[新しいプロジェクト]ダイアログボックスを開くには、[ファイル]»[新規プロジェクトVisual C ++テンプレートリストからWin32プロジェクトを選択し、プロジェクトに名前を付けて、[ OK ]をクリックします。
  1. 次のダイアログボックスで、現在のプロジェクト設定がWindowsアプリケーションであることが表示される場合があります。 [次へ]をクリックして、アプリケーションタイプをDLLに変更します。


  1. [完了]を選択してDLLを作成します。 MSVCは、プロジェクトと同じ名前の1つのソース(.cpp)ファイルを使用してDLLプロジェクトを作成します。また、 stdafx.cppファイルを生成します。 stdafx.cppファイルは必要ですが、通常は編集する必要はありません。
 

ソースファイルを編集する

  1. すべてのDLLファイルが必要な場合はlibrary.DetermineあなたのDllMain関数のニーズや編集機能のエントリポイントであるDllMain関数を、持っている必要があります。
  • ライブラリの特定の初期化を行う必要がない限り、MSVCが作成したデフォルトのDllMainで十分です。この関数は何もしないことに注意してください。
BOOL APIENTRY DllMain( HANDLE hModule,
                        DWORD  ul_reason_for_call,
                        LPVOID lpReserved )
{
    return TRUE;
}
  • ライブラリの初期化が必要な場合は、より完全なDllMainが必要になる場合があります。
BOOL WINAPI DllMain(  
         HINSTANCEhinstDLL,  // DLLモジュールへのハンドル
         DWORD fdwReason,     // 呼び出し理由
         LPVOID lpReserved )  // 予約済み
{
    // 起動理由に基づいて必要なアクションを実行します
    switch( fdwReason )
    {
    case DLL_PROCESS_ATTACH:
        // 新プロセスに対して1回初期化をする
        // DLLの読み込みに失敗したらFalseを返す            
        break;

    case DLL_THREAD_ATTACH:        
        // スレッド固有の初期化をする
        break;        
   
    case DLL_THREAD_DETACH:
        // スレッド固有のクリーンアップをする
        break;
   
    case DLL_PROCESS_DETACH:        
        // 必要なクリーンアップを行う
        break;    
    }
        return TRUE;
}
  1. DllMain関数が完了したら、DLLからアクセスする予定のルーチンを記述します。例えば:
//関数の宣言
int GetSphereSAandVol(double radius, double* sa, double* vol);
double GetSA(double radius);
double GetVol(double radius);

...

int GetSphereSAandVol(double radius, double* sa, double* vol)
//与えられた半径に対する表面積と体積を求めます
{
    if(radius < 0)
    return false; //半径が負であればFalse(0)を返します
        *sa = GetSA(radius);
        *vol = GetVol(radius);
        return true;
}

double GetSA(double radius)
{
    return 4 * M_PI * radius * radius;
}

double GetVol(double radius)
{
    return 4.0/3.0 * M_PI * pow(radius, 3.0);
}
  1. DLLを正しくコンパイルするには、 pow関数(つまり、power、 pow(x、y)はx ^ yと同等)と定数M_PI(つまり、3.14159)を宣言する必要があります。これを行うには、の先頭にある#include "stdafx.h"の下に2行のコードをcppファイルの先頭に挿入します。 コードは次のようになります。


#include "stdafx.h"
#include "math.h" // pow関数を定義するライブラリ
#define M_PI 3.14159 // M_PI定数を宣言します


この時点で、DLLをコンパイルしてリンクできます。ただし、このままではDLLは関数をエクスポートしないため、実際には役に立ちません。
 

シンボルのエクスポート

DLL内の関数にアクセスするには、目的のシンボルをエクスポートするようにコンパイラーに指示する必要があります。ただし、最初にC++の名前装飾の問題に対処する必要があります。 MSVCはソースの拡張子が.cppまたは.cxxの場合、ソースをC++としてコンパイルします。ソースファイルの拡張子が.cの場合、MSVCはそれをCとしてコンパイルします。ファイルをC++としてコンパイルする場合、関数名は通常出力コードで装飾されます。この場合関数名に余分な文字が追加されるため、問題になる可能性があります。この問題を回避するには、次のように関数宣言で関数を「extern "C"」として宣言します。

extern "C" int GetSphereSAandVol(double radius、double * sa、double * vol);

これにより、コンパイラが名前をC++装飾で装飾するのを防ぎます。
警告:C++装飾がないと、ポリモーフィック関数は使用できません。

C++の装飾が終了したら、実際に関数をエクスポートできます。エクスポートする関数をリンカに通知するには、2つの方法があります。最初の、そして最も簡単な方法は、エクスポートする関数の関数プロトタイプで__declspec(dllexport)タグを使用することです。これを行うには、次のように、宣言と定義にタグを追加します。

extern "C" __declspec(dllexport)int GetSphereSAandVol(double radius、double * sa、double * vol);
..。
__declspec(dllexport)int GetSphereSAandVol(double radius、double * sa、double * vol)
{{
..。
}


2番目の方法は、エクスポートする関数を明示的に宣言するdefファイルを使用することです。.defファイルは、リンカが何をエクスポートするかを決定するために使用する情報を含むテキストファイルで、次の形式となります。

LIBRARY   <Name to use inside DLL>
DESCRIPTION "<Description>"
EXPORTS
    <First export>   @1
    <Second export>  @2
    <Third export>   @3
    ...


サンプルDLLでは、.defファイルは次のようになります。
LIBRARY   EasyDLL
DESCRIPTION "Does some sphere stuff."
EXPORTS  
    GetSphereSAandVol   @1


DLLプロジェクトを適切に作成した場合、リンカは自動的にプロジェクトディレクトリ内のプロジェクトと同じ名前のdefファイルを探します。このオプションを変更するには、[プロジェクト] »[プロパティ]を選択します。 Linkerフォルダーで、[入力]プロパティページをクリックし、[モジュール定義ファイル]プロパティを/DEF: <filename>.defに変更します。

MicrosoftのDEFファイルを使用したDLLからエクスポートも参照してください。



呼び出し規約を指定する

DLLをコンパイルする前に行う必要がある最後のことは、エクスポートする関数の呼び出し規約を指定することです。通常、2つの選択肢があります。C呼び出し規約または標準呼び出し規約で、Pascal、WINAPIとも呼ばれます。ほとんどのDLL関数は標準呼び出し規約を使用しますが、LabVIEWはどちらも呼び出すことができます。

Cの呼び出し規約を指定する場合は何もする必要はありません。 [プロジェクト]»[プロパティ]»[C / C ++]»[詳細]で特に指定しない限り、これがデフォルトです。関数をC呼び出しとして明示的に宣言する場合は、関数の宣言と定義で__cdeclキーワードを使用します。

extern "C" __declspec(dllexport) int __cdecl GetSphereSAandVol(double radius, double* sa, double* vol);
...
__declspec(dllexport) int __cdecl GetSphereSAandVol(doublt radius, double* sa, double* vol)
{
     ...
}


標準呼び出し規約を指定するには、関数の宣言と定義に__stdcallキーワードを配置します。

extern "C" int __stdcall GetSphereSAandVol(double radius, double* sa, double* vol);
...
int __stdcall GetSphereSAandVol(doublt radius, double* sa, double* vol)
{
     ...
}

標準呼び出し規約を使用する場合、関数名はDLL内で装飾されています。 これは__declspec(dllexport)メソッドではなく関数をエクスポートするdefファイルを使用すると回避できます。したがって、NIはstdcall関数をエクスポートするためにdefファイルメソッドを使用することをお勧めします。


 

DLLのビルド

コードを記述し、エクスポートする関数を宣言し、呼び出し規約を設定すると、DLLをビルドする準備が整います。 [ビルド] »[ビルド<プロジェクト>]を選択して、DLLをコンパイルおよびリンクします。これで、LabVIEWからDLLを使用またはデバッグする準備が整いました。添付のEasyDLL.zipファイルには、このDLLの作成に使用されるVisual C++ワークスペースと、DLLにアクセスするLabVIEW VIが含まれています。

次のステップ

Attachments