注釈: この記事は、Calling C/C++ DLLs Containing Simple and Complex Datatypes from LabVIEW を翻訳したものです。内容に相違がある場合、英語の資料が正文となっております。
概観
LabVIEW開発者はLabVIEWからC/C++のDLLを呼び出すことがありますが、始めはLabVIEWとC/C++の間のデータタイプの違いから、DLLとデータの送受信を行うことに抵抗を感じることがあるかもしれません。
この記事に添付されたサンプルは、LabVIEWとDLLの間で数値(int、float、double、など)、配列、そして文字列などのシンプルなデータタイプから、ポインタ、構造体(クラスタ)、構造体の配列や、構造体の配列を含む構造体の配列などの複雑なデータタイプを渡す方法をLabVIEW開発者の方々にお見せするために作成されました。
また、このサンプルではLabVIEWとDLLの間で、データを渡す方法-関数が値渡しでデータを渡し、return ステートメントでデータを戻すか、リファレンス渡しでデータを戻すか、についても説明します。
このサンプルでは下記のケースを取り上げます:
データ型 | 呼び出し型
|
---|
1. 数値(整数) | a) 値を戻す (return ステートメント) |
2. 数値配列 | b) ポインタを戻す(returnステートメント) |
3. 文字列 | c) パラメータを渡す(値渡し) |
4. 2次元配列 | d) リファレンスで値を戻す(リファレンス渡し) |
5. (単純なデータ型を含む)単純な構造体 |
|
6. (構造体や配列を含む)複雑な構造体 |
|
添付されたファイル
- LabVIEWWrapper.zip: 各関数の呼び出し方の例を含むLabVIEWライブラリ (.lvlib)
- PassingDataSampleDLL.zip: ANSI C DLLのソースコードとDLL。CVIでかかれたものですが、Visual Studioでコンパイル可能なことを確認済み
- CTestApplication.zip: C DLLをANSI Cで呼び出す例。Visual Studioで作成。
サンプルのヒエラルキー
サンプルに含まれる多数のVIは共有ライブラリをインポートウィザードで自動的に生成されました。ただし、ウィザードはすべてのライブラリ関数に対してラッパーVIを生成できるわけではないため、一部のVIは未完成です。それでもこのウィザードはDLLを呼び出すためのはじめの一歩にはなります。
共有ライブラリをインポートウィザードの使用例については下記の資料を参照してください。
チュートリアル: 共有ライブラリをインポートウィザードで C/C++ の DLL 関数のラッパーVIを作成する
共有ライブラリをインポートウィザードが適応できなかったVIについては、「共有ライブラリをインポートウィザードの例外」セクションを参照してください。
サンプル内のVIは、下記の仮想フォルダに含まれています。
- Import Shared Llibrary Wizard Generated VIs: 共有ライブラリをインポートウィザードで自動的に正しく生成されたVI
- Dereferencing Pointers: ポインタをデリファレンスするために役立つVI。これらはMoveBlockもしくはGetValueByPointer関数を使用します。
詳細は、LabVIEW で C/C++ の DLL からのポインタをデリファレンスするを参照してください。 - Custom Controls For Structs: DLL内の構造体を表す指定タイプ定義
- Completed, Corrected and Added VIs: 共有ライブラリをインポートウィザードの例外を回避するために追加されたVI
共有ライブラリをインポートウィザードの例外
下記のケースでは共有ライブラリをインポートウィザードが正しく対応できませんでした。
VIが生成されない
下記の場合VIは生成されませんでした。
- 関数が、数値、文字列、voidあるいはポインタ以外を戻す場合。この場合データはポインタとして扱い、LabVIEWでは戻り値のデータタイプを符号なしポインタサイズ整数に設定します。
サンプルlvlibではこれらのVIは手動で生成し、VI名の末尾に「Added」を追加しています。
未完成のVI
下記の場合、生成されたVIは未完成でした。
サンプルlvlibではこれらのVIを手動で完成させて、VI名の末尾に「Completed」を追加しています。
不正確なVI
下記の場合、生成されたVIは正確に生成されませんでした。
- 関数がポインタのポインタ(文字列や2次元配列)を戻す場合。これらは二度でリファレンスされる必要があります。
- 関数に、配列や文字列を含む構造体(クラスタ)を入力される場合。この場合、各要素がそれぞれでリファレンスされる必要があります。
サンプルlvlibではこれらのVIを修正し、VI名の末尾に「Corrected」を追加しています。
関数とVIのリスト(データタイプと呼び出しタイプ)
下記にてC DLLの関数とその関数を正しく呼び出すためのVIをリストしています。
- 数値 (整数)
- 値を戻す (return ステートメント)
関数: int ReturningAValue_Integer (void);
VI: Returning A Value Integer.vi
自動生成されたVIのステータス: 正常動作 - ポインタを戻す(returnステートメント)
関数: int* ReturningAValue_PointerToInteger (void);
VI: Returning A Value Pointer To Integer Complete.vi
自動生成されたVIのステータス: 未完成 - パラメータを渡す(値渡し)
関数: int PassingParameters_Integer (int x, int y);
VI: Passing Parameters Integer.vi
自動生成されたVIのステータス: 正常動作 - リファレンスで値を戻す(リファレンス渡し)
関数: void ReturningValuesByReference_Integer (int x, int y, int *sum);
VI: Returning Values By Reference Integer.vi
自動生成されたVIのステータス: 正常動作
- 数値配列
- 値を戻す (return ステートメント)
関数: int* ReturningAValue_ArrayOfIntegers (int length);
VI: Returning A Value Array Of Integers Complete.vi
自動生成されたVIのステータス: 未完成 - ポインタを戻す(returnステートメント)
関数: N/A (arrays variables are already pointers)
VI: N/A
自動生成されたVIのステータス: N/A - パラメータを渡す(値渡し)
関数: int PassingParamters_ArrayOfIntegers (int x[], int length);
VI: Passing Paramters Array Of Integers.vi
自動生成されたVIのステータス: 正常動作 - リファレンスで値を戻す(リファレンス渡し)
関数: void ReturningValuesByReference_ArrayOfIntegers (int *x, int length, int **newArray, int *newLength);
VI: Returning Values By Reference Array Of Integers Complete.vi
自動生成されたVIのステータス: 未完成
- 文字列
- 値を戻す (return ステートメント)
関数: char* ReturningAValue_String (void);
VI: Returning A Value String.vi
自動生成されたVIのステータス: 正常動作 - ポインタを戻す(returnステートメント)
関数: N/A (arrays variables are already pointers)
VI:N/A
Auto Generated VI Status: N/A - パラメータを渡す(値渡し)
関数: int PassingParamters_String (char *str);
VI: Passing Paramters String.vi
自動生成されたVIのステータス: 正常動作 - リファレンスで値を戻す(リファレンス渡し)
関数: void ReturningValuesByReference_String (char *str, char **newString);
VI: Returning Values By Reference String Corrected.vi
自動生成されたVIのステータス: 不正確
- 2次元配列
- ReturningAValue_2DArrayOfIntegers
関数: int** ReturningAValue_2DArrayOfIntegers (int rows, int cols);
VI: Returning A Value 2D Array Of Integers Complete.vi
自動生成されたVIのステータス: 未完成 - ポインタを戻す(returnステートメント)
関数: N/A (arrays variables are already pointers)
VI: N/A
自動生成されたVIのステータス: N/A - パラメータを渡す(値渡し)
関数: int PassingParamters_2DArrayOfIntegers (int *x, int rows, int cols);
VI: Passing Paramters 2D Array Of Integers Corrected.vi
自動生成されたVIのステータス: 不正確 - リファレンスで値を戻す(リファレンス渡し)
関数: void ReturningValuesByReference_2DArrayOfIntegers (int rows, int cols, int ***newArray);
VI: Returning Values By Reference 2D Array Of Integers Complete.vi
自動生成されたVIのステータス: 未完成
- (単純なデータ型を含む)シンプルな構造体
- 値を戻す (return ステートメント)
関数: struct simpleStructCircle ReturningAValue_SimpleStruct(void);
VI: Returning A Value Simple Struct Added.vi
自動生成されたVIのステータス: 未生成 - ポインタを戻す(returnステートメント)
関数: struct simpleStructCircle* ReturningAValue_PointerToSimpleStruct(void);
VI: Returning A Value Pointer To Simple Struct Added.vi
自動生成されたVIのステータス: 未生成 - パラメータを渡す(値渡し)
関数: float PassingParamters_SimpleStruct (struct simpleStructCircle circle);
VI: Passing Paramters Simple Struct.vi
自動生成されたVIのステータス: 正常動作 - リファレンスで値を戻す(リファレンス渡し)
関数: void ReturningValuesByReference_SimpleStruct (struct simpleStructCircle circle, struct simpleStructCircle *largerCircle);
VI: Returning Values By Reference Simple Struct.vi
自動生成されたVIのステータス: 正常動作 - 構造体の配列を戻す
関数: void ReturningValuesByReference_ArrayOfSimpleStruct (struct simpleStructCircle **circleArray, int length);
VI: Returning Values By Reference Array Of Simple Struct Complete.vi
自動生成されたVIのステータス: 未完成
- (構造体や配列を含む)複雑な構造体
- 値を戻す (return ステートメント)
関数: struct complexStructPolygon ReturningAValue_ComplexStruct (void);
VI: Returning A Value Complex Struct Added.vi
自動生成されたVIのステータス: 未生成 - ポインタを戻す(returnステートメント)
関数: struct complexStructPolygon* ReturningAValue_PointerToComplexStruct (void);
VI: Returning A Value Pointer To Complex Struct Added.vi
自動生成されたVIのステータス: 未生成 - パラメータを渡す(値渡し)
関数: int PassingParamters_ComplexStruct (struct complexStructPolygon triangle);
VI: Passing Paramters Complex Struct Corrected.vi
自動生成されたVIのステータス: 不正確 - リファレンスで値を戻す(リファレンス渡し)
関数: void ReturningValuesByReference_PointerToComplexStruct (struct complexStructPolygon* triangle);
VI: Returning Values By Reference Pointer To Complex Struct Corrected.vi
自動生成されたVIのステータス: 不正確 - 構造体の配列を戻す
関数: void ReturningValuesByReference_ArrayOfComplexStruct (struct complexStructPolygon **triangles, int length);
VI: Returning Values By Reference Array Of Complex Struct Corrected.vi
自動生成されたVIのステータス: 不正確
スプレッドシートで閲覧されたい場合、下記のファイルを参照してください。
ListOfFunctionsAndVIs.xlsx
まとめ・次のステップ
LabVIEWとC/C++ DLLとの間でデータのやり取りをするのは、特に複雑なデータ型やポインタを使用する際には難しい場合もあります。この記事のサンプルを参照しながらDLLをLabVIEWで呼び出してみてください。