ディレクトリ
10パラメータ処理
第3章では、基本データ型とポインタのSWIGの治療を説明しました。特にような、プリミティブ型int
とdouble
ターゲット言語の種類を対応するマッピングされます。他のすべての場合は、ポインタは構造体、クラス、配列、および他のユーザー定義データ型を参照するために使用されています。しかし、特定の用途では、特定のデータ型のSWIGの取り扱いを変更することが望ましいです。たとえば、関数の引数を介して複数の値を返すようにしたいかもしれません。この章では、これを行うための技術のいくつかを説明しています。
第3章では、基本データ型SWIGとポインタの処理を説明します。具体的には、(例えば、プリミティブ型
int
とはdouble
)ターゲット言語の対応するタイプにマッピングされます。他のすべてのタイプのポインタ構造体、クラス、アレイ、および他のユーザ定義のデータ型を参照するために使用されます。ただし、一部のアプリケーションでは、SWIGは、特定のデータ型の取り扱いを変更したいです。たとえば、関数のパラメータを介して複数の値を返すようにしたいかもしれません。この章では、これらのアクションを実行するための手法のいくつかを説明しています。
10.1 typemaps.i
図書館
このセクションでは説明しtypemaps.i
、一般的に、引数変換の特定のプロパティを変更するために使用-ライブラリファイルを。
このセクションでは説明し
typemaps.i
、通常、特定のプロパティの変換のためのパラメータを変更するために使用-ライブラリファイルを。
10.1.1はじめに
あなたは、このようなC関数を持っていたと仮定します。
次のようにC関数があるとします。
void add(double a, double b, double *result) {
*result = a + b;
}
ソースコードを読んでから、関数がの値格納されていることは明らかであるdouble *result
パラメータ。SWIGは関数本体を調べていないので、これは基本的な動作であることを知る方法はありません。
これに対処する一つの方法は、使用することですtypemaps.i
。このようなライブラリファイルと書き込みインタフェースコードを:
ソースコードを読み取ることによって、その値が関数に格納されていることは明らかである
double *result
パラメータ。SWIGは関数本体をチェックしないので、その機能の基本的な振る舞いを知る方法はありません。一つの解決策は、使用することです
typemaps.i
、次のようにライブラリファイルと書き込みインタフェースコードを:
// Simple example using typemaps
%module example
%include "typemaps.i"
%apply double *OUTPUT { double *result };
%inline %{
extern void add(double a, double b, double *result);
%}
%apply
ディレクティブを使用すると、型に特殊なタイプの処理ルールを適用しようとしていることをSWIGに指示します。double *OUTPUT
仕様は、型の引数からの出力値を返す方法を定義するルールの名前ですdouble *
。この場合には-このルールは、中括弧に記載されているデータ型のすべてに適用されますdouble *result
。
その結果、モジュールが作成されると、あなたは今(Pythonのために示す)は、このような機能を使用することができます。
%apply
SWIGの手順は、アプリケーションの特定の種類のルールを処理する特殊なタイプであることを伝えます。double *OUTPUT
仕様では、ルールがタイプする方法を定義し、ルールの名前であり、double *
出力パラメータの値を返します。この規則は、この例のように、括弧に記載されているすべてのデータ型に適用されますdouble *result
。あなたは今(Python用)以下の機能を使用できるように、作成されたモジュールの結果:
>>> a = add(3, 4)
>>> print a
7
>>>
このケースでは、通常、第三引数に返される出力値が魔法のように関数の戻り値に変換されているかを見ることができます。これは明らかに、特別な製造にはもはや必要があるため、使用する機能がはるかに容易になりdouble *
、オブジェクトを何とか関数に渡します。
タイプマップが型に適用されると、それはタイプと名前のすべての将来の発生のために有効にとどまります。たとえば、次のように書くことができます:
この例では、出力値が通常魔法関数の戻り値に変換三番目のパラメータに返されるかを見ることができます。明らかに、これはそれが簡単に機能を使用できるようになり、特別に製造する必要がなくなりました
double *
オブジェクトを、いくつかの方法で関数に渡します。マッピングは種類のタイプに適用されると、それが有効な遺跡を登場するすべてのタイプと名前の将来のためです。たとえば、次のように書くことができます:
%module example
%include "typemaps.i"
%apply double *OUTPUT { double *result };
%inline %{
extern void add(double a, double b, double *result);
extern void sub(double a, double b, double *result);
extern void mul(double a, double b, double *result);
extern void div(double a, double b, double *result);
%}
...
この場合、double *OUTPUT
ルールは、以下の機能のすべてに適用されます。
TYPEMAP変換も複数の戻り値に拡張することができます。たとえば、次のコードを考えてみます。
この例では、
double *OUTPUT
ルールは、後続のすべての機能に適用されます。変換タイプ・マッピングはさらに、戻り値に拡張することができます。たとえば、次のコードを考えてみます。
%include "typemaps.i"
%apply int *OUTPUT { int *width, int *height };
// Returns a pair (width, height)
void getwinsize(int winid, int *width, int *height);
この場合、関数は次のように使用することができるように、複数の値を返します。
この例では、関数は次のように使用することができるように、複数の値を返します。
>>> w, h = genwinsize(wid)
>>> print w
400
>>> print h
300
>>>
またもののことに留意すべきである%apply
ディレクティブは、データ型に関連付けるタイプマップルールに使用されている、あなたも引数に直接ルール名を使用することができます。たとえば、あなたはこれを書くことができます:
またの使用にもかかわらず、ことに留意すべきである
%apply
タイプに関連付けられた命令とデータ型マッピングルールが、あなたはまた、引数に直接ルール名を使用することができます。たとえば、次のようにインタフェースファイルを書き込むことができます。
// Simple example using typemaps
%module example
%include "typemaps.i"
%{
extern void add(double a, double b, double *OUTPUT);
%}
extern void add(double a, double b, double *OUTPUT);
彼らは明示的に削除または何か他のものに再定義されるまで、タイプマップは有効です。タイプマップをクリアするには、%clear
ディレクティブを使用する必要があります。例えば:
それが明示的に削除されたり、これまで他のタイプとして再定義されるまで、タイプマッピングは有効のままになります。タイプマッピングをクリアするには、使用する
%clear
命令を。例えば:
%clear double *result; // Remove all typemaps for double *result
10.1.2入力パラメータ
ポインタは実際には単一の入力値を保持していることをSWIGに指示以下のタイプマップ:
以下のタイプ・マッピングはSWIGを伝え、実際には、ポインタのみの入力値を保存:
int *INPUT
short *INPUT
long *INPUT
unsigned int *INPUT
unsigned short *INPUT
unsigned long *INPUT
double *INPUT
float *INPUT
使用する場合は、値はポインタの代わりに渡すことができます。たとえば、この機能を考えてみます。
使用される場合には、ポインタ値を渡すことは許されません。たとえば、次の関数を考えてみます。
double add(double *a, double *b) {
return *a + *b;
}
さて、このSWIGインタフェースを考慮してください。
さて、SWIGインタフェースファイルを作成することを検討して:
%module example
%include "typemaps.i"
...
%{
extern double add(double *, double *);
%}
extern double add(double *INPUT, double *INPUT);
関数はスクリプト言語のインタプリタで使用される場合、それは次のように動作します:
スクリプト言語インタプリタでこの機能を使用すると、次のように動作します:
result = add(3, 4)
10.1.3出力パラメータ
以下のタイプマップルールは、ポインタは、関数の出力値であることをSWIGを教えてください。使用するときは、関数を呼び出す際の引数を指定する必要はありません。代わりに、一つ以上の出力値が返されます。
マッピング規則の種類は次のとおりSWIG、関数ポインタの出力値を教えてください。使用に際しては、関数を呼び出すときにパラメータを提供する必要はありません。しかし、一つ以上の出力値を返します。
int *OUTPUT
short *OUTPUT
long *OUTPUT
unsigned int *OUTPUT
unsigned short *OUTPUT
unsigned long *OUTPUT
double *OUTPUT
float *OUTPUT
前の例に示すように、これらの方法を用いることができます。たとえば、あなたがこのC関数を持っている場合:
前の例で示したように、これらの方法を用いることができます。たとえば、次のC関数を持っている場合:
void add(double a, double b, double *c) {
*c = a + b;
}
SWIGインタフェースファイルは次のようになります。
SWIGインタフェースファイルは次のようになります。
%module example
%include "typemaps.i"
...
%inline %{
extern void add(double a, double b, double *OUTPUT);
%}
この場合、単一の出力値が返されるが、これは制限ではありません。(以前に示されるように)出力値の任意の数は、複数の引数に出力ルールを適用することによって戻すことができます。
関数はまた、値を返す場合は、引数と一緒に返されます。たとえば、あなたがこれを持っていた場合:
この例では、単一の出力値が返されるが、これは限定するものではありません。(上図)は、複数の出力パラメータにルールによっては、出力値の任意の数を返すことができます。
関数はまた、値を返す場合、それはパラメータで返されます。たとえば、あなたが持っている場合:
extern int foo(double a, double b, double *OUTPUT);
この関数は、このような2つの値を返します。
この関数は2つの値を返します。
iresult, dresult = foo(3.5, 2)
10.1.4入力/出力パラメータ
ポインタは、入力と出力値の両方として機能するときには、次のタイプマップを使用することができます。
ポインタは、入力値と出力値の両方として使用する場合、以下の型マッピングを使用することができます。
int *INOUT
short *INOUT
long *INOUT
unsigned int *INOUT
unsigned short *INOUT
unsigned long *INOUT
double *INOUT
float *INOUT
これはこのようなものかもしれません使用していますAC機能:
Cは、このような機能を持っています:
void negate(double *x) {
*x = -(*x);
}
作るためにx
、両方の入力および出力値としての機能を、インタフェースファイルにこのような機能を宣言する。
用
x
インターフェースファイル関数で宣言され、入力および関数値の出力値の両方:
%module example
%include "typemaps.i"
...
%{
extern void negate(double *);
%}
extern void negate(double *INOUT);
今スクリプト内で、あなたは、単に通常の関数を呼び出すことができます。
さて、スクリプトで簡単に関数を呼び出すことができます。
a = negate(3); # a = -3 after calling this
一つ微妙なポイントINOUT
のルールは、多くのスクリプト言語は、プリミティブオブジェクト(整数や文字列などの単純なオブジェクトが変更になっていないことを意味する)の可変性制約を強制することです。基本的なC関数は、この例の場合と同様このため、あなただけの場所でオブジェクトの値を変更することはできません。したがって、INOUT
ルールはなく、直接、元の入力オブジェクトの値を上書きするより新しいオブジェクトとして変更された値を返します。
互換性に関する注意:INOUT
として知られるように使用されるルールBOTH
SWIGの以前のバージョンインチ 後方互換性は維持さが、推奨されません。
INOUT
元のオブジェクトスクリプト言語実装変動制約の多く(例えば、整数や文字列などの単純なオブジェクトを意味し、変更してはならない)というルールの機微。だから、あなたは、この例のように、所定の位置に基本的なC関数をオブジェクトの値を変更することはできませんよう。従って、INOUT
新たなオブジェクトが返されるように、ルールは、代わりに、直接、元の入力オブジェクトの値を覆う、値を変更しました。互換性に関する注意:SWIGの以前のバージョンでは、
INOUT
ルールが以前に知られていましたBOTH
。これは、下位互換性のために残されていますが、推奨されません。
10.1.5使用別の名前
以前に示されているように、%apply
ディレクティブは適用するために使用することができINPUT
、OUTPUT
およびINOUT
異なる引数名にタイプマップを。例えば:
先に示したように、
%apply
命令が使用することができINPUT
、OUTPUT
およびINOUT
名前マッピングのタイプが異なるパラメータに適用されます。例えば:
// Make double *result an output value
%apply double *OUTPUT { double *result };
// Make Int32 *in an input value
%apply int *INPUT { Int32 *in };
// Make long *x inout
%apply long *INOUT {long *x};
ルールをクリアするには、%clear
ディレクティブが使用されます。
使用するために、ルールを一掃するために
%clear
コマンドを:
%clear double *result;
%clear Int32 *in, long *x;
タイプマップファイルまたはマッチングの末尾に定義の点から有効になるように、タイプマップ宣言はレキシカルスコープれる%clear
宣言。
タイプマッピング宣言は字句ので、ファイルの末尾にタイプマッピングポイントを定義することによって開始するか、マッチング、スコープされ
%clear
、それが宣言される前にすべての力に入ります。
10.2入力値に制約を課します
様々な入力値の扱いを変更することに加えて、制約を適用するためにタイプマップを使用することも可能です。たとえば、多分あなたは値が正であること、またはポインタがNULLであることを保証します。これは含めて行うことができるconstraints.i
ライブラリファイル。
また、種々の入力値の変更処理、それに加えて、制約型キャストを適用することができます。たとえば、多分あなたは値が正の数、または非NULLポインタであることを確認します。これを含めることができる
constraints.i
ライブラリーを完了すること。
例10.2.1単純な制約
制約ライブラリは最高の次のインターフェイスファイルによって示されています:
以下のinterfacesファイルがある
constraints.i
ライブラリ最高の説明:
// Interface file with constraints
%module example
%include "constraints.i"
double exp(double x);
double log(double POSITIVE); // Allow only positive values
double sqrt(double NONNEGATIVE); // Non-negative values only
double inv(double NONZERO); // Non-zero values
void free(void *NONNULL); // Non-NULL pointers only
このファイルの振る舞いは、あなたが期待するように正確です。引数のいずれかが制約条件に違反した場合は、スクリプト言語の例外が発生します。その結果、不正な値をキャッチし、神秘的なプログラムがクラッシュを防ぐというようにすることが可能です。
あなたが期待するとおりに、ファイル上のアクション。パラメータのいずれかが制約に違反した場合、例外はスクリプト言語をスローされます。結局、それは、間違った値をキャプチャする神秘的なクラッシュを防ぎ、などがあります。
10.2.2制約方法
次の制約は、現在利用可能です
以下の制限が現在利用可能です。
POSITIVE Any number > 0 (not zero)
NEGATIVE Any number < 0 (not zero)
NONNEGATIVE Any number >= 0
NONPOSITIVE Any number <= 0
NONZERO Nonzero number
NONNULL Non-NULL pointer (pointers only).
新しいアプリケーションの10.2.3データ型の制約
制約ライブラリはプリミティブなCのデータ型をサポートしていますが、使用して新しいデータ型に適用することは容易です%apply
。例えば :
制約ライブラリサポートだけのオリジナルCデータ型が、使用が
%apply
簡単に新しいデータ型に適用することができます。例えば:
// Apply a constraint to a Real variable
%apply Number POSITIVE { Real in };
// Apply a constraint to a pointer type
%apply Pointer NONNULL { Vector * };
「数」と「ポインタ」の特殊なタイプは、それぞれ任意の数値とポインタ変数の型に適用することができます。後で制約を削除するには、%clear
ディレクティブを使用することができます。
特定の種類
Number
及びPointer
それぞれ任意の数、およびポインタ変数のタイプに適用することができます。後で制約を削除するには、使用することができます%clear
コマンドを:
%clear Real in;
%clear Vector *;