Perl バインディングの使用法
この章では、Caché Perl バインディングを使用する Perl コードの具体例を紹介します。ここで説明する内容は以下のとおりです。
-
Perl バインディングの基礎 — Caché データベース・オブジェクトへのアクセスと操作に関する基本事項です。
-
タイ変数の使用法 — Perl バインディングへのアクセスに使用可能な Perl 固有の方法
-
コレクションの使用法 — Caché のリストと配列を反復処理します。
-
リレーションシップの使用法 — 埋め込みオブジェクトを操作します。
-
クエリの使用法 — Caché クエリとダイナミック SQL クエリを実行します。
-
%Binary データの使用法 — Caché %Binary と Perl 順序配列との間でデータを移動します。
-
例外処理 — Perl バインディングからの Perl 例外とエラー・メッセージを処理します。
-
Perl バインディングの制約と制限 — Perl と Caché 間の特定のデータ型の処理方法の違いによって適用される制限事項です。
ここで紹介する例の多くは、<cachesys>/dev/perl/samples/ にあるサンプル・プログラムに収録されています (ご使用のシステムの <cachesys> の場所については、"Caché インストール・ガイド" の "Caché の既定のインストール・ディレクトリ" を参照してください)。コードを簡略化するため、引数処理とエラー・トラップの文 (try/catch) は除外されています。完全なサンプル・プログラムをロードして実行する方法の詳細は、"サンプル・プログラム" を参照してください。
Perl バインディングの基礎
Caché Perl バインディング・アプリケーションは非常にシンプルです。以下は、完全なサンプル・プログラムです。
use Intersys::PERLBIND;
eval {
# Connect to the Cache' database
$url = "localhost[1972]:Samples";
$user = "_SYSTEM";
$password = "SYS";
$conn = Intersys::PERLBIND::Connection->new($url,$user,$password,0);
$database = Intersys::PERLBIND::Database->new($conn);
# Create and use a Cache' object
$person = $database->create_new("Sample.Person", undef);
$person->set("Name","Doe, Joe A");
print "Name: ",$person->get("Name"), "\n";
};
このコードは Intersys::PERLBIND モジュールをインポートして、以下の処理を実行します。
-
Caché データベースの Samples ネームスペースに接続します。
-
Caché データベースへの接続に必要な情報を定義します。
-
Connection オブジェクト ($conn) を作成します。
-
Connection オブジェクトを使用して、Database オブジェクト ($database) を作成します。
-
-
Caché オブジェクトを作成し、使用します。
-
Database オブジェクトを使用して、Caché Sample.PersonOpens in a new tab クラスのインスタンスを作成します。
-
Sample.PersonOpens in a new tab オブジェクトの Name プロパティを設定します。
-
Name プロパティを取得し、出力します。
-
以下のセクションでは、これらの基本処理について詳しく説明します。
Caché データベースへの接続
Caché データベースのネームスペースへ接続するための基本的な手順は以下のとおりです。
-
物理的な接続を確立します。
$conn = Intersys::PERLBIND::Connection->new($url,$userid,$password,$timeout);
Connection->new() メソッドは、物理的に Caché データベースのネームスペースに接続します。$url パラメータは、Connection オブジェクトがアクセスするサーバとネームスペースを定義します。Connection クラスには、Kerberos を使用した安全な接続を確立する new_secure() メソッドもあります。これらのメソッドの詳細は、"接続" を参照してください
-
論理接続を作成します。
$database = Intersys::PERLBIND::Database->new($conn);
Connection オブジェクトを使用して Database オブジェクトを作成します。これは、ネームスペースのクラスを使用してデータベースを操作できるようにする論理接続です。
以下のコードによって、Samples ネームスペースへの接続が確立されます。
$address ="localhost"; # server TCP/IP address ("localhost" is 127.0.0.1) $port = "1972"; # server TCP/IP port number $namespace = "SAMPLES"; # sample namespace installed with Cache' $url = $address."[$port]:".$namespace; $user = "_SYSTEM"; $password = "SYS"; $conn = Intersys::PERLBIND::Connection->new($url,$user,$password,0); $database = Intersys::PERLBIND::Database->new($conn);
Caché Database メソッドの使用法
Intersys::PERLBIND::Database クラスを使用すると、Caché クラスのメソッドを実行して、サーバ上の Caché オブジェクトに接続できます。Database クラスのメソッドで実行できる基本操作は以下のとおりです。
-
オブジェクトの作成。
create_new() メソッドを使用して、新しい Caché オブジェクトを作成します。構文は、以下のとおりです。
$object = $database->create_new($class_name, $initial_value)
$class_name は、$database によってアクセスされるネームスペース内の Caché クラスの名前です。例えば、Sample.PersonOpens in a new tab クラスの新規インスタンスを作成する場合は、以下の文を実行します。
$person = $database->create_new("Sample.Person", undef);
この例では、$person の初期値は未定義です。
-
オブジェクトを開く。
openid() メソッドを使用して、既存の Caché オブジェクトを開きます。構文は、以下のとおりです。
$object = $database->openid($class_name, $id, $concurrency, $timeout)
例えば、以下の文は、id の値が 1 である Sample.PersonOpens in a new tab オブジェクトを開きます。
$person = $database->openid("Sample.Person", "1", -1, 0);
同時処理とタイムアウトは既定値に設定されています。
-
クラス・メソッドの実行。
以下の構文を使用してクラス・メソッドを実行できます。
$result = $database->run_class_method($classname,$methodname,LIST)
LIST は、メソッド引数のリストです。例えば、前述の $database->openid() の例は以下のコードと同等です。
$person = $database->run_class_method("Sample.Person","%OpenId","1");
このメソッドは、Caché の ##class 構文と類似しています。以下はコードの例です。
$list = $database->run_class_method("%ListOfDataTypes","%New",undef); $list->Insert("blue");
上記のコードは、以下の ObjectScript コードとまったく同じです。
set list=##class(%ListOfDataTypes).%New() do list.Insert("blue")
Caché Object メソッドの使用法
Intersys::PERLBIND::Object クラスは、Caché オブジェクトへのアクセスを提供します。Object クラスのメソッドで実行できる基本操作は以下のとおりです。
-
プロパティの取得と設定。
プロパティにアクセスするには、アクセサ・メソッド get() と set() を使用します。これらのメソッドの構文は以下のとおりです。
$value = $object->get($propname) $object->set($propname,$value)
以下はその例です。
$person->set("Name","Adler, Mortimer"); $name = $person->get("Name");
プライベート・プロパティと多次元プロパティは、Perl バインディングからはアクセスできません。
-
オブジェクト・メソッドの実行。
オブジェクト・メソッドを直接呼び出すことで、それらを実行できます。
$answer = $object->MethodName(LIST);
以下はその例です。
$answer = $person->Addition(17,20);
run_obj_method() によっても、同じ処理を実行できます。
$answer = $object->run_obj_method($MethodName,LIST);
以下はその例です。
$answer = $object->run_obj_method("Addition", 17, 20);
このメソッドは、直接アクセスできない継承メソッド (%Save や %Id など) を呼び出すときに役立ちます。
-
オブジェクトの保存。
オブジェクトを保存するには、run_obj_method() を使用して %Save を呼び出します。
$object->run_obj_method("%Save")
保存されているオブジェクトの ID を取得するには、run_obj_method() を使用して %Id を呼び出します。
$id = $object->run_obj_method("%Id")
-
メソッドおよびプロパティに関する情報の取得。
Object クラスには、オブジェクト内のメソッドおよびプロパティに関する情報を返すメソッドがいくつかあります。get_methods() および get_properties() メソッドは、そのコンテキストに応じて、使用可能な項目数か有効な項目名のリストのどちらかを返します。
$methodcount = $object->get_methods(); # scalar context @methodlist = $object->get_methods(); # list context $propcount = $object->get_properties(); # scalar context @proplist = $object->get_properties(); # list context
is_method() および is_property() メソッドは、文字列が有効な項目名であるかどうかを判別するテストを実行します。
$bool = $object->is_method($methodname); $bool = $object->is_property($propname);
タイ変数の使用法
Perl バインディングによって返されたオブジェクトをハッシュにタイし、そのハッシュを介してオブジェクトのプロパティにアクセスできます。以下はその例です。
$object = $database->openid("Sample.Person", "1", -1, 0);
$person = tie %person,"Intersys::PERLBIND::ObjectHash",( _object => $object)
$name = $person{"Name"};
# The following line is equivalent to $person->set("Name","Tregar, Sam");
$person{"Name"} = "Tregar, Sam";
$person->get("Name") によって個人の名前を取得する代わりに、タイを使用することで、ハッシュの $person{"Name"} から名前を取得できます。
タイからの返り値を使用して、メソッドを実行できます。または、Perl の "tied" ビルトインを使用して、メソッドを実行できます。以下はその例です。
$ans = $person->Addition(12,17);
print "ans=$ans\n";
$ans = tied(%person)->Addition(12,17);
print "ans=$ans\n";
どちらの場合でも、値 29 が返されます。
また、タイを使用して、プロパティのリストを繰り返し処理することもできます。
while (($property, $value ) = each(%person)) {
print "propety=$property value=$value\n";
}
以下はその完全な例です。
$database = Intersys::PERLBIND::Database->new($conn);
$personobj = $database->openid("Sample.Person", "1", -1, 0);
$person = tie %person,
"Intersys::PERLBIND::ObjectHash",( _object => $personobj);
while (($propname, $value) = each(%person)) {
print "property $propname = $value\n";
}
この例では、各プロパティとその値を表示する以下の出力が生成されます。
property Age = 61
property DOB = 1942-01-18
property SSN = 295-62-8728
property Home = Intersys::PERLBIND::Object=SCALAR(0x1831ee4)
property Name = Adler, Mortimer
property Office = Intersys::PERLBIND::Object=SCALAR(0x183eed0)
property Spouse =
property FavoriteColors = Intersys::PERLBIND::Object=SCALAR(0x1831e3c)
コレクションとリストの使用法
Caché %Collection オブジェクトは、他の Perl バインディング・オブジェクトと同様に処理されます。Caché %ListOpens in a new tab 変数は、Perl の配列参照にマップされます。この後のセクションでは、コレクションとリスト両方の使用方法を示します。
%Collection オブジェクト
コレクションを操作するには、Caché %Collection クラスのオブジェクト・メソッドを使用します。以下の例は、Caché %ListOfDataType コレクションを操作する方法を示しています。
# Create a %ListOfDataTypes object and add a list of colors
$newcolors = $database->run_class_method("%ListOfDataTypes","%New",undef);
@color_list = qw(red blue green);
for $color (@color_list) {
$newcolors->Insert($color);
print " added >$color<\n";
};
# Add the list to a Sample.Person object
$person = $database->openid("Sample.Person",$id,-1,0);
$person->set("FavoriteColors",$newcolors);
# Get the list back from $person and print it out.
$colors = $person->get("FavoriteColors");
print "Number of colors: ",$colors->get("Size"), "\n";
do {
$color = $colors->GetNext($i);
print " New Color #$i = $color\n" if defined($i);
} until (!defined($i));
# Remove and replace the second element
$colors->RemoveAt(2) if $colors->get("Size") > 0;
$colors->InsertAt("purple",2);
# Show the changes to the collection
print("Modified 'FavoriteColors' list:\n");
do {
$color = $colors->GetNext($i);
print " Element #$i = $color\n" if defined($i);
} until (!defined($i));
%List 変数
Perl バインディングでは、Caché %ListOpens in a new tab 変数は Perl の配列参照にマップされます。
Perl の配列にはサイズの制限がありませんが、Caché %ListOpens in a new tab 変数は約 32 KB に制限されています。実際の上限は、データ型と、各要素に必要なヘッダ・データのサイズによって異なります。%ListOpens in a new tab データのサイズがこの上限に達する可能性がある場合は、適切なエラー・チェック (この後の例を参照) を使用してください。
このセクションの例では、以下の Caché クラスが使用されています。
Class Sample.List Extends %Persistent
{
Property CurrentList As %List;
Method InitList() As %List {
q $LB(1,"hello",3.14) }
Method TestList(NewList As %List) As %Integer {
set $ZTRAP="ErrTestList"
set ItemCount = $LISTLENGTH(NewList)
if (ItemCount = 0) {set ItemCount = -1}
q ItemCount
ErrTestList
set $ZERROR = ""
set $ZTRAP = ""
q 0 }
}
TestList() メソッドは、Perl 配列が有効な Caché リストかどうかのテストに使用されます。リストが長すぎる場合、このメソッドはエラーをトラップし、0 (Perl の False) を返します。リストが有効な場合は、要素の数が返されます。有効なリストの要素数が 0 の場合は、-1 が返されます。
以下のコードは、Sample.List オブジェクトを作成して InitList() メソッドから事前定義済みの Caché リストを取得し、それを Perl 配列に変換してその配列に関する情報を表示します。
$listobj = $database->create_new("Sample.List",undef);
$arrayref = $listobj->InitList();
@array = @$arrayref;
print "Initial List from Cache:\n";
print "array address = $arrayref\n";
print "array contents = @array\n";
print "There are ",scalar(@array)," elements in the list:\n";
for ($i=0;$i<scalar(@array);$i++) {
print " element ",$i+1," = [$array[$i]]\n";
}
このコードは以下の出力を生成します。
Initial List from Cache:
array address = ARRAY(0x18d3d04)
array contents = Cache to Perl: hello! 1 3.14
There are 4 elements in the list:
element 1 = [Cache to Perl: hello!]
element 2 = [1]
element 3 = []
element 4 = [3.14]
element 3 の Caché の NULL リスト要素は、Perl 配列では undef 値に相当します。
以下のコードは両方向にリストを渡します。このコードは、小規模な Perl 配列を作成してそれを Caché オブジェクトの CurrentList プロパティに格納し、その後で、同じプロパティから再取得して Perl 配列に再変換します。
@oldarray = (1, undef, 2.78,"Just a small list.");
$listobj->set("CurrentList",\@oldarray);
$arrayref = $listobj->get("CurrentList");
@newarray = @$arrayref;
print "\n\nThis list is from property CurrentList:\n";
print "There are ",scalar(@newarray)," elements in the list:\n";
for ($i=0;$i<scalar(@newarray);$i++) {
print " element ",$i+1," = [$newarray[$i-1]]\n";
}
print "\nThe old and new arrays ";
if ("@oldarray" eq "@newarray")
{print "match:\n"}
else
{print "DON'T match:\n"};
print " old:>@oldarray<\n",
" new:>@newarray<\n";
このコードは以下の出力を生成します。
This list is from property CurrentList:
There are 4 elements in the list:
element 1 = [Just a small list.]
element 2 = [1]
element 3 = []
element 4 = [2.78]
The old and new arrays match:
old:>1 2.78 Just a small list.<
new:>1 2.78 Just a small list.<
Cache %ListOpens in a new tab 変数に Perl 配列をすべて格納できるようにすることは重要です。以下のコードは、過度に大規模な Perl 配列を作成し、それを CurrentList プロパティに格納しようとします。
# Create a large array and print array information.
$longitem = "1022 character element".(1234567890 x 100);
@array =("This array is too long.");
$cache_list_size = length($array[0]);
for ($i=0;$i<33;$i++) {
push(@array,$longitem);
$cache_list_size += length($longitem);
};
print "\n\nNow for a HUGE list:\n";
print "Total bytes required by Cache' list: more than $cache_list_size\n";
print "There are ",scalar(@array)," elements in the ingoing list.\n\n";
# Check to see if the array will fit.
$bool = $listobj->TestList(\@array);
print "TestList() reports that the array ";
if ($bool) {print "is OK, and has $bool elements.\n";}
else {print "will be damaged by the conversion.\n"};
# Pass the array to Cache', get it back, and display the results
$listobj->set("CurrentList",\@array);
$badarrayref = $listobj->get("CurrentList");
@badarray = @$badarrayref;
print "There are ",scalar(@badarray)," elements in the returned list:\n";
for ($i=0;$i<scalar(@badarray);$i++) {
$line = $badarray[$i];
# long elements are shortened for readability.
if (length($line)> 1000) {substr($line,10,980) = "..."};
print " element ",$i+1," = [$line]\n";
}
出力をわかりやすく示すため、正常なセクションについては要素が省略されています。Unicode システムでは以下の出力が生成されます。
Now for a HUGE list:
Total bytes required by Cache' list: more than 33749
There are 34 elements in the ingoing list.
TestList() reports that the array will be damaged by the conversion.
There are 17 elements in the returned list:
element 1 = [This array is too long.]
element 2 = [1022 chara...90123456789012345678901234567890]
element 3 = [1022 chara...90123456789012345678901234567890]
element 4 = [1022 chara...90123456789012345678901234567890]
element 5 = [1022 chara...90123456789012345678901234567890]
element 6 = [1022 chara...90123456789012345678901234567890]
element 7 = [1022 chara...90123456789012345678901234567890]
element 8 = [1022 chara...90123456789012345678901234567890]
element 9 = [1022 chara...90123456789012345678901234567890]
element 10 = [1022 chara...90123456789012345678901234567890]
element 11 = [1022 chara...90123456789012345678901234567890]
element 12 = [1022 chara...90123456789012345678901234567890]
element 13 = [1022 chara...90123456789012345678901234567890]
element 14 = [1022 chara...90123456789012345678901234567890]
element 15 = [1022 chara...90123456789012345678901234567890]
element 16 = [1022 chara...90123456789012345678901234567890]
element 17 = [1022 chara...90123456ray is too long.ï´√ȇ1022 c]
破損したリストに記録されているのは、元の 34 要素のうちの 17 要素のみなので、17 要素が破損していることになります。
リレーションシップの使用法
リレーションシップは、リレーションシップ・オブジェクトとそのメソッドによってサポートされています。
以下の例は、$company オブジェクトと一連の $employee オブジェクト間にある 1 つまたは複数のリレーションシップを使用してレポートを生成します。このコードでは、リレーションシップ・オブジェクトの $emp_relationship によって、$company オブジェクトに関連付けられているすべての $employee オブジェクトへのアクセスが可能になっています。
$company = $database->openid("Sample.Company", "1", -1, 0);
$emp_relationship = $company->get("Employees");
$index=undef;
do {
$employee = $emp_relationship->run_obj_method("GetNext",$index);
# "GetNext" sets $index to the next valid index, or to undef if
# there are no more records.
if ($index) {
$name = $employee->get("Name");
$title = $employee->get("Title");
$company = $employee->get("Company");
$compname = $company->get("Name");
$SSN = $employee->get("SSN");
print "index=$index employee name=$name SSN=$SSN ",
"title=$title companyname=$compname\n";
};
} while ($index);
以下のコードは、新しい従業員レコードを作成してそれをリレーションシップに追加し、$company の保存時にその従業員の情報を自動的に保存します。
$new_employee = $database->create_new("Sample.Employee","");
$new_employee->set("Name",$name);
$new_employee->set("Title",$title);
$new_employee->set("SSN",$SSN);
$emp_relationship->run_obj_method("Insert", $new_employee);
$company->run_obj_method("%Save");
クエリの使用法
クエリを実行するための基本的な手順は以下のとおりです。
-
クエリ・オブジェクトを作成します。
$query = $database->alloc_query()
ここで、$database は Intersys::PERLBIND::Database オブジェクト、$query は Intersys::PERLBIND::Query オブジェクトです。
-
クエリを作成します。
SQL クエリは prepare() メソッドを使用します。
$query->prepare($sql_query, $sqlcode)
$sql_query は、実行するクエリを含む文字列です。
Caché クラスのクエリは prepare_class() メソッドを使用します。
$query->prepare_class($class_name, $query_name, $sqlcode)
-
パラメータ値を割り当てます。
$query->set_par($idx, $val)
set_par() メソッドは、パラメータ $idx に値 $val を割り当てます。既存のパラメータの値を変更するには、新しい値を指定して set_par() を再度呼び出します。Query クラスには、既存のパラメータに関する情報を返すいくつかのメソッドが用意されています。
-
クエリを実行します。
$query->execute($sqlcode)
execute() メソッドは、set_par() の呼び出しで定義されているパラメータを使用して、結果セットを生成します。
-
データ行を取得します。
@data_row = $query->fetch($sqlcode)
fetch() メソッドを呼び出すたびに、結果セットからデータ行が取得され、そのデータがリストとして返されます。取得するデータがない場合は、空のリストが返されます。Query クラスには、行内の列に関する情報を返すいくつかのメソッドが用意されています。
Sample.Person からデータを取得する簡単な SQL クエリを以下に示します。
# Allocate, prepare, set a parameter, and get a result set: $query = $database->alloc_query(); $sql_query = "SELECT ID, Name, DOB, SSN FROM Sample.Person ~WHERE Name %STARTSWITH ?"; $sqlcode=0; $query->prepare($sql_query, $sqlcode); $query->set_par(1,"A"); $query->execute($sqlcode); # Fetch each row in the result set, and print the # name and value of each column in a row: $rownum = 1; while (@data_row = $query->fetch($sqlcode)) { print "Row $rownum ===================\n"; $colnum = 1; foreach $col_data (@data_row) { $col_name = $query->col_name($colnum); print " $col_name: $col_data\n"; $colnum++; } $rownum++ }
Intersys::PERLBIND::Query クラスの詳細は、"Perl クライアント・クラス・リファレンス" の章の "クエリ" を参照してください。Caché のクエリの詳細は、"Caché オブジェクトの使用法" の "クラス・クエリの定義と使用" を参照してください。
%Binary データの使用法
Perl バインディングでは、Perl pack() および unpack() 関数を使用して、Caché %BinaryOpens in a new tab と Perl の順序配列間でデータを変換します。Caché バイナリ・データの各バイトは、Perl では 0 ~ 255 の整数として表されます。
このセクションの例では、以下の Caché クラスが使用されています。
Class Sample.Bin Extends %Persistent
{
Property B As %Binary;
Method GetBinary() As %Binary {
q "hello"}
Method SetBinary(PerlBin As %Binary) {
s ^foobar=PerlBin}
}
このクラスは、さまざまな方法 (プロパティ値、メソッドの返り値、メソッドの引数、グローバル変数) で %BinaryOpens in a new tab データを使用します。以下のコードは、Caché と Perl 間で、バイナリ・データを双方向に複数回変換します。Perl アプリケーションは、そのたびにデータを変更します。
最初の入力はメソッドの結果です。GetBinary() メソッドは、%BinaryOpens in a new tab 値 "hello" を返します。この値がアンパックされ、結果として得られる配列が出力されます。
$binobj = $database->openid("Sample.Bin",1,-1,0);
$B_packed = $binobj->run_obj_method("GetBinary");
@B_unpacked = unpack("c*",$B_packed ); # "c*" is the template for an ord
foreach $c (@B_unpacked) {
# "%c" turns the ord value $c into a character
printf "[%c]",$c
}
print "\n";
出力の先頭行は以下のようになります。
[h][e][l][l][o]
ここで、最初のバイトを "j" に変更し、配列を再パックします。パックした値は Caché %BinaryOpens in a new tab の B プロパティに格納され、変更した Caché オブジェクトが保存されます。
$B_unpacked[0] = ord("j");
$B_packed = pack("c*",@B_unpacked);
$binobj->set("B",$B_packed);
$binobj->run_obj_method("%Save");
2 番目の入力はプロパティ値です。B プロパティから %BinaryOpens in a new tab の "jello" 値を取得し、アンパックします。今回、プログラムは、新しい要素を配列の最後に追加することで値を再び変更します。
$B_packed = $binobj->get("B");
@B_unpacked = unpack("c*",$B_packed ); # "c*" is the template for an ord
push @B_unpacked, ord("!");
foreach $c (@B_unpacked) {
printf "[%c]",$c
}
print "\n";
};
出力結果は前の行と結合され、以下のようになります。
[h][e][l][l][o]
[j][e][l][l][o][!]
最後に、配列を再度パックし、それを引数として SetBinary() メソッドに渡します。このメソッドは、渡された引数を Caché のグローバル変数 ^foobar に格納します。
$B_packed = pack("c*",@B_unpacked);
$binobj->run_obj_method("SetBinary",$B_packed);
例外処理
Perl バインディングでは、Perl 例外を使用して、C バインディングなどからのエラーを返します。
以下に、Perl 例外の使用例を示します。
eval {
$answer = $variant2->run_obj_method("PassLastByRefAdd17","10","goodbye");
};
if ($@) {
print "Perl exception $@\n";
}
# Attempt to open a nonexistent id
eval {
$causeException = $database2->openid("NonExistent", "1", -1, 0);
};
if ($@) {
print "Perl exception $@\n";
}
%Status 返り値の処理
メソッドで宣言した返り値のタイプが %StatusOpens in a new tab である場合、状態値は返されません。代わりに例外がスローされます。例えば、%StatusOpens in a new tab を返す以下のような Caché メソッドを呼び出すとします。
Class User.PerlStatus Extends %Persistent{
ClassMethod MyStatus() as %Status
{
q $$$ERROR(-137,"bad fine structure constant")
}
}
以下の Perl バインディング プログラムは、MyStatus() メソッドを呼び出し、例外をキャプチャして、返された状態値を出力します。
# TestStatus.pl: illustrate handling a bad status return from COS
use Intersys::PERLBIND;
my $user="_SYSTEM";
my $password="SYS";
my $url = "localhost[1972]:USER";
eval {
$conn = Intersys::PERLBIND::Connection->new($url,$user,$password,0);
$database = Intersys::PERLBIND::Database->new($conn);
$status=$database->run_class_method("User.PerlStatus", "MyStatus");
# exception is thrown before we get here
print "status=$status\n";
};
if ($@) {
print "Caught exception: $@\n";
} else {
print "\nSample finished running\n";
}
エラー・レポート
引数または返り値の処理時、C バインディングからのエラー・メッセージは Perl バインディング層によって特別な形式にフォーマットされます。この情報は、インターシステムズのサポート窓口が問題を診断する際に使用します。
以下はエラー・メッセージの例です。
file=PERLBIND.xs line=71 err=-1 message=cbind_variant_set_buf()
cpp_type=4 var.cpp_type=-1 var.obj.oref=1784835886
class_name=%Library.RelationshipObject mtd_name=GetNext argnum=0
エラー・メッセージの構成要素は以下のとおりです。
メッセージ |
意味 |
---|---|
file=PERLBIND.xs |
エラーが発生したファイル。 |
line=71 |
ファイル内の行番号。 |
err=-1 |
C バインディングから返されるコード。 |
message= cbind_variant_set_buf() |
C バインディングのエラー・メッセージ。 |
cpp_type=4 |
メソッド引数の cpp タイプまたは返り値のタイプ。 |
var.cpp_type=-1 |
variant の cpp タイプ。 |
var.obj.oref=1784835886 |
variant の oref。 |
class_name= %Library.RelationshipObject |
メソッド呼び出しの対象となるオブジェクトのクラス名。 |
mtd_name=GetNext |
メソッド名。 |
argnum=0 |
引数の番号。0 は最初の引数、-1 は返り値を表します。 |
Perl バインディングの制約と制限
Perl バインディングには以下の制限が適用されます。これらの制限は、通常、Perl と Caché 間の特定のデータ型の処理方法の違いに関係しています。
-
Perl バインディングは ObjectScript のメソッドとデータ型の制限を継承します。例えば、Caché システムで %StringOpens in a new tab が 32K に制限されている場合、Perl プログラムで Caché 文字ストリームに対して 32K を超す書き込みを試行すると、プログラムでエラーが発生します。
-
Caché と Perl では、基本のデータ型の数値域や、仮数および指数の範囲などのパラメータが異なります。この相違によって、プログラムで大きな数の操作 (例えば、およそ 15 桁超の整数の比較など) を実行したときに問題が発生することがあります。これに対処するため、このようなデータは Caché から %BinaryOpens in a new tab 文字列として取得します。
-
32 ビットと 64 ビット・システムの両方で操作する場合、数値処理は 32 ビットの制限を受ける可能性があることに注意してください。32 ビット・システムでは、整数変数は 32 ビットに制限され、10 進変数は仮数と指数の両方を符号付整数の 32 ビットに収める必要があります。
-
%StatusOpens in a new tab パラメータを参照によって渡すことはできません ("%Status 返り値の処理" も参照してください)。これに対処するには、値を整数として渡します。
-
一部の Caché ライブラリ・メソッドは、Caché ローカル配列を、参照によって渡されたパラメータとして受け取り、返します。Caché 言語バインディングは、ローカル配列パラメータ付きのメソッドをサポートしていません。これに対処するには、Caché 側でローカル配列を処理する Caché ラッパ・メソッドを記述します。
-
Perl コードで子プロセス (または Windows スレッド) がフォークされると、接続が失われます。例えば、以下のコードでは空命令の子プロセスがフォークされ、その後、メイン・プログラムから接続が失われます。子プロセス用に接続の参照がコピーされ、子プロセスが終了すると閉じられます。
my $pid = fork(); if ( !defined( $pid)) { die( "fork() failed\n"); } if ( $pid == 0) { # child print( "child: calling exit()\n"); exit( 0); } else { # parent waitpid( $pid, 0); # wait for the child to exit } my $ret = $db->run_class_method( "%SYSTEM.OBJ", "Version", ());