Oracle Forms Developer and Oracle Reports Developer
アプリケーション作成ガイド
リリース6i

J00449-01

戻る次へ

目次

索引

6
オープン・アーキテクチャの利用

この章では、Forms DeveloperおよびReports Developerで利用できる、オープンで拡張可能な環境開発を利用する上で役立つガイドラインを提供します。

  説明 

6.1項「OLEオブジェクトとActiveXコントロールの処理」 

サポートするコンポーネント・テクノロジの内容を説明し、OLEオブジェクトおよびActiveXコントロールをはじめとするアプリケーションを作成するための手順およびガイドラインを提供します。 

6.2項「外部ファンクションを使用したアプリケーションのカスタマイズ」 

3GL外部ファンクションを使用してアプリケーションのカスタマイズと、拡張を行う方法を説明します。 

6.3項「Form Builderアプリケーションの作成と修正を行うためのオープンAPIの使用」 

オープンAPIの概要を説明し、さらに、オープンAPIを使用してForm Builderアプリケーションの作成と変更を行う方法を説明します。 

6.4項「ODBCデータソースに対して実行するアプリケーションの設計」 

ODBCサポートの内容を説明し、さらに、ODBCに対してアプリケーションを実行するための詳細な手順およびガイドラインを提供します。 

6.1 OLEオブジェクトとActiveXコントロールの処理

この項ではOLEおよびActiveXの内容を説明し、さらにこのテクノロジの利用方法を説明します。この項では、次の項目について説明します。

注意: OLEおよびActiveXのサポートは、Windowsプラットフォームのみに制限されています。

6.1.1 OLE

Object Linking and Embedding (OLE)はMicrosoft の標準機能で、様々なソフトウェア・コンポーネントを1つのアプリケーションに統合して再使用できます。

たとえば、アプリケーションをMicrosoft Excel文書と統合すると、Forms Developer(またはReports Developer)およびMicrosoft Excelの機能を提供できるようになります。ユーザーは、Forms DeveloperまたはReports Developerの機能を使用してデータベースのデータの表示や操作を行う一方で、Microsoft Excelで提供されるテキスト処理機能を使用して文書の書式を整えることができます。

OLEオブジェクトをアプリケーションに取り込めば、専用のコンポーネントの様々なグループをシームレスに統合して完全なアプリケーションを作成できます。最初から新規にアプリケーション全体を作成する必要はありません。アプリケーションを短時間に、低コストで配布できます。

6.1.1.1 OLEを利用する場合

OLEは次のような場合に使用します。

6.1.1.2 OLEサーバーとOLEコンテナについて

OLEの基本概念は、クライアントとサーバーです。クライアントとは、別のアプリケーションのサービスを要求し利用するアプリケーションです。サーバーとは、このようなサービスを提供するアプリケーションです。

6.1.1.3 埋込みオブジェクトとリンク・オブジェクトについて

OLEオブジェクトをアプリケーションにリンクまたは埋め込むことができます。

リンクと埋込みの間には機能的違いはありません。OLEコンテナは、リンク・オブジェクトの場合であっても、埋込みオブジェクトの場合であっても、同じコードを実行していずれも同様に処理します。唯一の違いは、OLEオブジェクトを埋め込むとアプリケーションのサイズが増えることです。この結果として考慮するべき点はパフォーマンス(特にファイル・サーバー)への影響です。アプリケーションのサイズが大きくなるほど、オープンやメモリーへのロードに時間がかかります。

6.1.1.4 レジストレーション・データベースについて

各クライアント・マシンにはOLEレジストレーション・データベースが含まれています。レジストレーション・データベースには、OLEオブジェクトを分類する一連のクラスが保存されています。レジストレーション・データベースに含まれている情報により、OLEコンテナにおける埋込みやリンクに使用可能なオブジェクト・クラスが決定されます。

OLEサーバー・アプリケーションでは、レジストレーション・データベースのメンバーとなる一連のクラスがエクスポートされます。各コンピュータには、レジストレーション・データベースが1つあります。OLEサーバー・アプリケーションのインストール時にレジストレーション・データベースが存在しない場合は、レジストレーション・データベースが1つ作成されます。

1つのOLEサーバー・アプリケーションによって、レジストレーション・データベースに多くのOLEクラスを追加できます。レジストレーション・データベースにクラスを追加するプロセスは、OLEサーバー・アプリケーションのインストールの間に透過的に行われます。たとえば、Microsoft Excelをインストールする場合、複数のクラスがレジストレーション・データベースに追加されます。レジストレーション・データベースにインストールされるクラスには、Excel Application、Excel Application5、Excel Chart、Excel Sheet、ExcelMacrosheet、ExcelWorkSheet などがあります。

6.1.1.5 OLEアクティブ化スタイルについて

OLEオブジェクトをアクティブ化することにより、OLEサーバー・アプリケーションの機能にアクセスできます。OLEオブジェクトをアクティブ化する方法には、内部アクティブ化と外部アクティブ化の2つがあります。

6.1.1.6 OLEオートメーションについて

OLEオブジェクト内のデータと対話したり、OLEオブジェクト内のデータを操作したいと考えることがあります。その場合に、PL/SQLおよびOLEオートメーションを使います。

OLEオートメーションにより、サーバー・アプリケーションで、OLEコンテナ・アプリケーションから起動できる一連のコマンドやファンクションを提供できます。これらのコマンドやファンクションを使用すれば、OLEコンテナ環境からOLEオブジェクトを操作できます。

Forms DeveloperおよびReports Developerでは、OLEサーバー・アプリケーションにより提供されるコマンドやファンクションには、PL/SQLを使用してアクセスします。OLEコマンドやファンクションの作成、操作、およびアクセスを行うためのPL/SQLアプリケーション・プログラミング・インタフェースは、ビルトインで提供されます。

注意: OLEコンテナ・アプリケーションのOLEオブジェクトの操作に利用できるオプションの多くは、OLEサーバー・アプリケーションによって決まります。たとえば、OLEポップアップ・メニューのオプション(別名OLE動詞)は、OLEサーバー・アプリケーションにより提供されます。オブジェクト・クラスなどの、レジストレーション・データベースに含まれている情報も、OLEサーバー・アプリケーションによって決まります。

6.1.1.7 OLEサポート

Forms DeveloperおよびReports Developerは、OLEオートメーションに加え、OLEサーバー・サポートおよびOLEコンテナ・サポートも提供します。

コンポーネント  コンテナ  サーバー・アプリケーション  OLE2オートメーション 

Form Builder 

あり 

なし 

あり 

Graphics Builder 

なし 

あり 

あり 

Procedure Builder 

なし 

なし 

なし 

Project Builder 

なし 

なし 

なし 

Query Builder 

なし 

なし 

なし 

Report Builder 

あり 

なし 

あり 

Schema Builder 

なし 

なし 

なし 

6.1.1.7.1 OLEコンテナ・サポート

OLEコンテナ・アプリケーションとして、Form BuilderおよびReport Builderでは次のことをサポートしています。

6.1.1.7.2 OLEサーバー・サポート

Graphics BuilderはOLEサーバー・アプリケーションです。Graphics Builderの図表をForms DeveloperアプリケーションやReports Developerアプリケーションに埋め込んだり、リンクしたりできます。

推奨事項: Graphics Builder図表をアプリケーションに追加する場合は、OLEオブジェクトとしての埋込みやリンクは行わないでください。図表は、チャート・ウィザードを使用してアプリケーションに追加してください。

6.1.1.7.3 OLEコンテナ・プロパティ

OLEコンテナ・プロパティにより、OLE表示属性、OLEコンテナとサーバーとの対話、コンテナの保存などが決まります。

注意: コンテナ・プロパティの他に、OLEオブジェクト・プロパティも設定できます。各OLEオブジェクトには複数のプロパティがあります。OLEオブジェクトのプロパティにアクセスするには、マウスの右ボタンをクリックしてポップアップ・メニューを表示します。

この項では、Forms DeveloperおよびReports DeveloperでサポートしているOLEコンテナ・プロパティを示します。

コンポーネント  プロパティ  説明 

Form Builder 

  • OLEアクティブ・スタイル

 

OLEコンテナ項目をアクティブ化するイベントを指定します。 ダブルクリック、フォーカスインまたは手動があります。 

 

  • OLEクラス

 

OLEコンテナに常駐できるOLEオブジェクトのクラスを決定します。 

 

  • OLE同一ウィンドウ・アクティブ

 

埋め込みOLEオブジェクトの編集にOLE内部アクティブ化を使うかどうかを指定します。  

 

  • OLEの詳細サポート

 

埋め込みオブジェクトのOLEサーバーで内部アクティブ化の際にインサイド・アウト・オブジェクト・サポートを使用可能にするかどうかを指定します。インサイド・アウト・アクティブ化により、複数の埋め込みオブジェクトに対して、OLEコンテナ内にアクティブな編集ウィンドウを持たせることができます。  

 

  • OLEポップアップ・メニュー項目

 

マウス・カーソルをOLEオブジェクト上に置いてマウスの右ボタンを押したときに、どのOLEポップアップ・メニューが表示され、使用可能になるかを決定します。OLEポップアップ・メニュー・コマンドによってOLEオブジェクトを操作します。 

 

  • OLEサイズ変更スタイル

 

OLEコンテナにおけるOLEオブジェクトの表示形式を決定します。  

 

  • OLEテナント形態

 

OLEコンテナにおけるOLEオブジェクトの表示方法を決定します。内容、アイコンまたはサムネイルがあります。 

 

  • OLEテナント・タイプ

 

OLEコンテナのテナントとなるOLEオブジェクトのタイプを決定します。埋込み、リンク、任意、静的またはなしがあります。 

 

  • OLEポップアップ・メニュー表示

 

マウスの右ボタンをクリックしたときにOLEオブジェクトと対話するためのコマンド・ポップアップ・メニューを表示するかどうかを決定します。  

 

  • OLEテナント・タイプ表示

 

OLEオブジェクト・タイプを定義する境界線がOLEコンテナを囲むかどうかを決定します。 

Report Builder 

新規作成 

OLEオブジェクトをレポート・アプリケーションに埋め込むことを指定します。 

 

ファイルから作成 

OLEオブジェクトをレポート・アプリケーションにリンクすることを指定します。 

 

アイコンとして表示 

OLEオブジェクトがアイコンとして表示されるかどうかを指定します。デフォルトでは、OLEオブジェクトは空のコンテナとして表示されます。 

6.1.1.7.4 OLE/ActiveXビルトイン

この項では、各コンポーネントでサポートされているOLEおよびActiveXビルトインをリストします。

コンポーネント  ビルトイン  説明 

Form Builder 

  • ACTIVATE_SERVER

 

OLEコンテナと対応付けられているOLEサーバーをアクティブ化して、OLEサーバーがOLEオートメーション・イベントをOLEコンテナから受け取ることができるようにします。  

 

  • ADD_OLEARGS

 

OLEオブジェクトのメソッドに渡される引数の型および値を設定します。 

 

  • CALL_OLE

 

指定されたOLEオブジェクトのメソッドにコントロールを渡します。  

 

  • CALL_OLE_<return type>

 

指定されたOLEオブジェクトのメソッドにコントロールを渡します。指定した型の戻り値を受け取ります。

CHAR、NUM、OBJ、RAW、VARのそれぞれの引数型に対応する5つのバージョンのファンクションが用意されています(戻り時のデータ型によって分けられます)。 

 

  • CLOSE_SERVER

 

OLEコンテナに対応付けられているOLEサーバーを非アクティブ化します。OLEサーバーとOLEコンテナの間の接続を終了します。 

 

  • CREATE_OLEOBJ

 

最初のフォームにおいてOLEオブジェクトを作成し、オブジェクトの永続性を確立します。2番目のフォームにおいて、以前にインスタンス化されたOLEオブジェクトの永続性を変更します。 

 

  • CREATE_VAR

 

空の名前未定可変レコードを作成します。

このファンクションには2つのバージョンがあります。1つはスカラー、もう1つは配列です。 

 

  • DESTROY_VARIANT

 

CREATE_VARファンクションにより作成された可変レコードを破棄します。  

 

  • EXEC_VERB

 

OLEサーバーで、動詞名または動詞索引により指定された動詞を実行します。OLE動詞により、OLEオブジェクトで実行できるアクションを指定します。 

 

  • FIND_OLE_VERB

 

OLE動詞索引を戻します。OLE動詞により、OLEオブジェクトで実行できるアクションが指定されます。各OLE動詞には対応するOLE動詞索引があります。  

 

  • GET_INTERFACE_POINTER

 

ハンドルをOLE2オートメーション・オブジェクトに戻します。 

 

  • GET_OLEARG_<type>

 

OLE引数スタックからn番目の引数を取得します。

CHAR、NUM、OBJ、RAW、VARのそれぞれの引数型に対応する5つのバージョンのファンクションが用意されています(データ型の値によって分けられます)。 

 

  • GET_OLE_MEMBERID

 

OLEオブジェクトの名前付きメソッドまたはプロパティのメンバーIDを取得します。 

 

  • GET_VAR_BOUNDS

 

OLE可変レコードの配列の範囲を取得します。 

 

  • GET_VAR_DIMS

 

OLE可変レコードが配列であるかどうかを判別します。配列である場合は、その配列が何次配列であるかを取得します。 

 

  • GET_VAR_TYPE

 

OLE可変レコードの型を取得します。 

 

  • GET_VERB_COUNT

 

OLEサーバーで認識される動詞の数を戻します。OLE動詞により、OLEオブジェクトで実行できるアクションが指定されます。使用できる動詞の数はOLEサーバーによって決まります。  

 

  • GET_VERB_NAME

 

指定された動詞索引と対応付けられている動詞名を戻します。 

 

  • INITIALIZE_CONTAINER

 

サーバー互換ファイルからのOLEオブジェクトをOLEコンテナに挿入します。 

 

  • INIT_OLE_ARGS

 

定義されてOLEオブジェクトのメソッドに渡される引数の数を設定します。 

 

  • LAST_OLE_ERROR

 

最新のOLEエラー条件を識別する番号を戻します。 

 

  • LAST_OLE_EXCEPTION

 

コールされたオブジェクトで発生した最新のOLE例外を識別する番号を戻します。 

 

  • OLEVAR_EMPTY

 

型VT_EMPTYのOLE可変レコード  

 

  • PTR_TO_VAR

 

まず、指定されたアドレスを含む型VT_PTRのOLE可変レコードを作成します。次に、ファンクションVARPTR_TO_VARによりその可変レコードと型を渡します。  

 

  • RELEASE_OBJ

 

OLEオブジェクトへの接続を停止します。 

 

  • SERVER_ACTIVE

 

指定されたコンテナと対応付けられているサーバーが実行中であるかどうかを示します。 

 

  • SET_OLE

 

OLEプロパティの値を変更します。

新規値のデータ型によって、NUMBER、VARCHAR、OLEVARの3種類のバージョンのプロシージャがあります。 

 

  • SET_VAR

 

新しく作成されたOLE可変レコードをその初期値に設定します。または、既存のOLE可変レコードを新規値にリセットします。

新規値のデータ型によってCHAR、NUMBER、OLEVAR、表の4種類のバージョンのプロシージャがあります。  

 

  • TABLE_FROM_BLOCK

 

表にブロックからデータを移入します。  

 

  • TO_VARIANT

 

OLE可変レコードを作成し、それを値に割り当てます。

このファンクションには4つのバージョンがあります。  

 

  • VARPTR_TO_VAR

 

可変レコードのポインタを単純な可変レコードに変更します。 

 

  • VAR_TO_TABLE

 

OLE配列可変レコードを読み込み、PL/SQL表にデータを移入します。 

 

  • VAR_TO_<type>

 

OLE可変レコードを読み込み、その値を等価のPL/SQL型に変換します。

CHAR、NUM、OBJ、RAW、TABLE、VARPTRのそれぞれの引数型に対応する6つのバージョンのファンクションが用意されています(データ型の値によって分けられます)。 

 

  • VAR_TO_VARPTR

 

既存の可変レコードを指し示すOLE可変レコードを作成します。  

Developer OLE2パッケージ 

  • ADD_ARG

 

指定された引数リストに引数を追加します。 

 

  • CREATE_ARGLIST

 

OLEサーバーに渡す引数リストを作成します。 

 

  • CREATE_OBJ

 

新しく作成されたOLEオブジェクトにハンドルを戻します。これは通常、スペルチェッカーなどのユーザー・インタフェースのないOLEオブジェクトに使われます。 

 

  • DESTROY_ARGLIST

 

指定した引数リストを破棄します。 

 

  • GET_CHAR_PROPERTY

 

OLEオブジェクトの文字プロパティを戻します。 

 

  • GET_NUM_PROPERTY

 

OLEオブジェクトの数値プロパティを戻します。 

 

  • GET_OBJ_PROPERTY

 

OLEオブジェクトのオブジェクト・タイプ・プロパティを戻します。 

 

  • INVOKE

 

指定したOLEサーバー・プロシージャを実行します。 

 

  • INVOKE_CHAR

 

指定したOLEサーバー・ファンクションを実行します。このファンクションは、文字値を戻します。 

 

  • INVOKE_NUM

 

指定したOLEサーバー・ファンクションを実行します。このファンクションは、数値を戻します。 

 

  • INVOKE_OBJ

 

指定したOLEサーバー・ファンクションを実行します。このファンクションは、オブジェクト・タイプ値を戻します。 

 

  • LAST_EXCEPTION

 

OLEエラーを戻します。 

 

  • SET_PROPERTY

 

OLEプロパティを指定した値に設定します。 

 

  • RELEASE_OBJ

 

指定したOLEオブジェクトのすべてリソースの割当てを解除します。 

6.1.1.8 OLEガイドライン

項目  推奨事項 

OLEオブジェクトの埋込みまたはリンク 

次の場合には、OLEオブジェクトをリンクします。

  • ユーザーがOLEサーバー環境においてOLEオブジェクトを処理する場合(ユーザーが外部アクティブ化を行いたいと考えている)。たとえば、作成したアプリケーションではなく、Microsoft Excelを使った方がスプレッドシートの編集を快適に行える場合に、OLEオブジェクトをリンクします。

  • OLEオブジェクトを複数のアプリケーションで使用する場合。

  • アプリケーションのサイズが気になる場合。

次の場合には、OLEオブジェクトを埋め込みます。

  • ユーザーが、アプリケーションを使ってOLEオブジェクトを処理できる場合。ユーザーが内部アクティブ化を行いたいと考えている場合。

  • 複数のOLEソース・ファイルを持つアプリケーションを維持するのではなく、1つのアプリケーションを維持する場合。

  • アプリケーションのサイズを気にしていない場合。

 

OLEアクティブ・スタイル 

外部アクティブ化を使用します。リンクされたオブジェクトをアクティブ化するには、外部アクティブ化による場合のみです。 

表示形式 

パフォーマンスを最適化する場合には、OLEオブジェクトの「表示形式」プロパティを「アイコン」に設定します。 

OLEオブジェクトの作成は設計時または実行時のどちらで行いますか? 

OLEオブジェクトは設計時に作成します。

OLEコンテナをForm Builderで作成する場合、OLEコンテナはForms Builderにより自動的に初期化されます。

対照的に、OLEオブジェクトを実行時に挿入する場合は、OLEオブジェクトを手動で初期化する必要があります。

注意: OLEオブジェクトをForms Runtimeの稼動時に手動で挿入すると、OLEオブジェクトは、次のレコード問合せまで、OLEコンテナに表示されます。後続のレコード問合せがあると、OLEコンテナはForm Builderで定義された状態で、またはデータベースからOLEオブジェクトが移入された状態で表示されます。  

移植性 

OLEオブジェクトがサポートされるのは、Microsoft Windowsのみです。移植性が問題になる場合は、OLEオブジェクトをアプリケーションに取り込まないでください。Forms Developer(またはReports Developer)で機能を開発するか、あるいは3GL外部ファンクションを開発することを検討してください。 

Report BuilderでのOLEプロパティの設定 

Report BuilderのOLEコンテナ・プロパティは、「OLEオブジェクトの作成」ダイアログでしか利用できません。すなわち、Report Builderのプロパティ・パレットには、OLEコンテナ・プロパティはありません。Report Builderで作業を行っている場合は、OLEプロパティを「OLEオブジェクトの作成」ダイアログで設定します。 

OLEオブジェクトの処理時は、次のガイドラインを考慮してください。

6.1.1.9 アプリケーションへのOLEオブジェクトの追加

OLEオブジェクトをアプリケーションに追加するための詳細な手順は、オンライン・ヘルプを参照してください。

6.1.1.10 OLEオブジェクトの操作

OLEサーバー・アプリケーションは、OLEオブジェクトのプログラム上の操作を可能にする一連のコマンドを提供します。

OLEオブジェクトの操作方法は次のとおりです。

6.1.1.11 OLEの例

この項では、OLEのスタート・ガイドとしていくつかの例を紹介します。

6.1.1.11.1 例1: バインド変数構文を使用したOLEプロパティの設定
 

フォーム・アプリケーションにおいて、:item('item_name').ocx.server_name.propertyバインド変数構文を使用して、プロパティ値を割り当てるか、または取り出すことができます。

例:

   :item('OLEitem').OCX.SpreadSheet.CellForeGroundColor:=
   :item('OLEitem').OCX.SpreadSheet.CellForeGroundColor + 1;

OLEitemは項目名、SpreadSheetはOLEコントロール・サーバー名、CellForeGroundColorはプロパティ名です。

6.1.1.11.2 例2: プロパティ・アセサーを使用したOLEプロパティの設定

フォーム・アプリケーションにおいて、プロパティ・アセサー・ファンクションおよびプロシージャを使用して、プロパティ値を取得、設定できます。

例:

   Variant OleVar;
   Variant := EXCEL_WORKSHEET.ole_Range(:CTRL.interface,
      To_variant('A1'));

EXCEL_WORKSHEETは、OLEインポータから作成されたプログラム単位の名前です。OLE_RANGEは、プロパティ・アセサー名です。

6.1.1.11.3 例3: Excelスプレッドシートのセルの変更

この例では、Excelスプレッドシートにおいてセル値を取得、設定します。

   PACKAGE spreadsheet IS
   procedure setcell(trow number, col number, val number);
   function getcell(trow number, col number) return number;
   END;

   PACKAGE BODY spreadsheet IS
   obj_hnd ole2.obj_type;		/* store the object handle */
   FUNCTION get_object_handle return ole2.obj_type IS
   BEGIN
     /* If the server is not active, activate the server
        and get the object handle.
     */
     if not forms_ole.server_active ('spreadsheet') then
       forms_ole.activate_server('spreadsheet');
       obj_hnd := forms_ole.get_interface_pointer('spreadsheet');
     end if;
     return obj_hnd;
   END;
    /*
   Excel cells are accessed with the following syntax in Visual Basic:
   ActiveSheet.Cells(row, column).Value
   In PL/SQL, we need to first get the active sheet using the   
   forms_ole.get_interface_pointer built-in.  We can then use that to call the   
   Cells method with the row and column in an argument list to get a handle to  
   that specific cell.  Lastly, we access the value of that cell.
   */
  
   PROCEDURE SETCELL (trow number, col number, val number) IS
     d ole2.obj_type;
     c ole2.obj_type;
     n number;
     lst ole2.list_type;
   BEGIN
     /* Activate the server and get the object handle
        to the spreadsheet.
     */
     d := get_object_handle;
     /* Create an argument list and insert the specified
        row and column into the argument list.
     */
     lst := ole2.create_arglist;
     ole2.add_arg(lst,trow);
     ole2.add_arg(lst,col);
     /* Call the Cells method to get a handle to the
        specified cell.
     */
     c := ole2.invoke_obj(d,'Cells',lst);
     /* Set the value of that cell. */
     ole2.set_property(c,'Value',val);
     /* Destroy the argument list and the cell object
        handle.
     */
     ole2.destroy_arglist(lst);
     ole2.release_obj(c);
   END;

    FUNCTION GETCELL(trow number, col number) return number IS
     c ole2.obj_type;
     d ole2.obj_type;
     n number;
     lst ole2.list_type;
   BEGIN
     /* Activate the server and get the object handle
        to the spreadsheet.
     */
     d := get_object_handle;
     /* Create an argument list and insert the specified
        row and column into the argument list.
     */
     lst := ole2.create_arglist;
     ole2.add_arg(lst,trow);
     ole2.add_arg(lst,col);
     /* Call the Cells method to get the value in the
        specified cell.
     */
     c := ole2.invoke_obj (d,'Cells',lst);
     n := ole2.get_num_property (c, 'Value');
     /* Destroy the argument list. */
     ole2.destroy_arglist(lst);
     ole2.release_obj(c);
     return n;
   END;
   END;

セルにアクセスするには、次のコードを使用します。

   spreadsheet.setcell(3, 5, 91.73);
   :block1.item1 := spreadsheet.getcell(2, 4);

6.1.2 ActiveXコントロール

ActiveXコントロール(OLEまたはOCXコントロールと呼ばれていたもの)は、スタンドアロン・ソフトウェア・コンポーネントで、アプリケーションに埋め込むことにより軽快なユーザー・インタフェース・コントロールを提供します。

ActiveXコントロールとOLEオブジェクトとの違いは次のとおりです。

6.1.2.1 ActiveXコントロールを利用する場合

ActiveXコントロールは通常、自己完結型機能性を追加することによりアプリケーションを拡張するために使用されます。

たとえば、タブ付プロパティ・パレット、スピン・コントロール、カレンダ・コントロール、ヘルプ・コントロールなどでアプリケーションを拡張できます。

独自のActiveXコントロールまたはOLEサーバーを開発するには、かなりの努力が必要です。サードパーティ・ベンダーにより開発および配布されているActiveXコントロールおよびOLEサーバーを使用することをお薦めします。

6.1.2.2 ActiveXコントロールの操作

各ActiveXコントロールは、一連のプロパティ、メソッドおよびイベントを提供します。プロパティによってActiveXコントロールの物理属性および論理属性が定義され、メソッドによってActiveXコントロールが実行するアクションが定義されます。イベントはActiveXコントロールの状態の変更を示します。

ActiveXコントロールの操作方法は次のとおりです。

ActiveXコントロールを操作するには、(Forms Developerの)STANDARDOLE2ビルトイン・パッケージを使用します。

6.1.2.3 ActiveXイベントへの応答

ActiveXイベントへの応答は、ActiveXイベント・パッケージまたはOn-Dispatch-Eventトリガーに独自のコードを書き込んで行います。

各ActiveXイベントは、イベント・パッケージに定義されているPL/SQLプロシージャに対応付けられています。コントロールがイベントを起動すると、プロシージャのコードは自動的に実行されます。

プロシージャ名は、対応するイベントを表す内部番号により決まります。イベントにより生成される制限付きプロシージャには、次に示すものに似たアプリケーション・プログラミング・インタフェースがあります。

PROCEDURE /*Click*/ event4294966696(interface OleObj);

注意: ActiveXプロシージャは制限モードで実行されます。On-Dispatch-Eventトリガー内でイベント・プロシージャをコールする際に、そのプロシージャが制限モードで実行されるのか、または非制限モードで実行されるのかを、FORMS4W.DISPATCH_EVENTコールを使用して明示的に定義できます。制限プロシージャの定義時に、OUTパラメータは監視されません。

6.1.2.4 ActiveXコントロールの配布

ActiveXコントロールを含むアプリケーションを利用するには、そのActiveXコントロールを利用する必要があります。

ActiveXコントロールを利用するには、次のことを行う必要があります。

注意: ActiveXコントロールは、サード・パーティのActiveXコントロール・ベンダーにより配布されたものなのか、アプリケーション開発ツールにバンドルされたものなのかにかかわらず、ActiveXコントロールを配布する前に、追加料金の支払いまたは追加ライセンスの取得が必要になる場合があります。

6.1.2.5 ActiveXサポート

サポートとは、ActiveXコントロールを作成、操作し、ActiveXコントロールとの通信を行う機能を備えていることです。

コンポーネント  コンテナ 

Form Builder 

あり 

Graphics Builder 

なし 

Procedure Builder 

なし 

Project Builder 

なし 

Query Builder 

なし 

Report Builder 

なし 

Schema Builder 

なし 

6.1.2.5.1 ActiveXプロパティ

この項では、Forms DeveloperでサポートされているActiveXプロパティをリストします。

コンポーネント  プロパティ  説明 

Form Builder 

OLEクラス 

OLEコンテナに常駐できるOLEオブジェクトのクラスを決定します。 

 

コントロール・プロパティ 

ActiveXコントロール・プロパティの設定を可能にします。

「ActiveXプロパティ」ダイアログへのアクセスは、プロパティ・パレットを使用するか、またはActiveXコントロールをクリックしてからマウスの右ボタンをクリックして行います。 

 

コントロールについて 

ActiveXコントロールに関する情報を表示します。 

 

コントロール・ヘルプ 

コントロール専用ヘルプ(利用できる場合) 

6.1.2.5.2 ActiveX/OLEビルトイン

各コンポーネントでサポートされているActiveXおよびOLEビルトインのリストは、6.1.1.7.4項を参照してください。

6.1.2.6 ActiveXガイドライン

項目  推奨事項 

独自のActiveXコントロールの作成 

独自のActiveXコントロールまたはOLEサーバーを開発するには、かなりの努力が必要です。サードパーティ・ベンダーにより開発および配布されているActiveXコントロールおよびOLEサーバーを使用することをお薦めします。  

ActiveXコントロールの初期化 

シングル・レコードはForms Runtimeの起動時にただちに初期化されるため、ブロック構造のActiveXコントロールを、「単一レコード」プロパティを「はい」に設定した状態で使用します。

複数レコードの場合、各レコードは、そのレコードにナビゲートするまで初期化されません。

初期化が行われない場合、ActiveXコントロール項目は空であるため、ActiveXコントロールがまったく利用できないといった印象を与えます。 

OLE可変レコード・タイプの管理 

  • Microsoft ExcelなどのOLEサーバーの中には可変レコード・タイプを使用するものがあります。可変レコード・タイプとの間で必要な変換を行うには、STANDARDビルトイン・パッケージを使用します。

  • 可変レコード・タイプの存続期間および有効範囲は、トリガーに限定されています(可変レコードのメモリー領域はトリガーの終了時に解放されます)。可変レコード・タイプの存続期間および有効範囲を拡張するには、To_Variant()の永続パラメータをTRUEに設定し、結果をグローバル変数に割り当てます。

注意: グローバルな可変レコードは、Destroy_Variant()を使用して明示的に破棄する必要があります。同様に、 Create_OleObj()を使用して作成されたOLEオブジェクトは有効範囲においてグローバルです(永続パラメータのデフォルトはTRUE)。Release_Obj()を明示的に呼び出してグローバル・オブジェクトを開放する必要があります。 

ActiveXファイルの移動 

ActiveXファイルは“インストール”ディレクトリに保持します。ActiveXファイルを別のディレクトリに移動しないでください。

インストール時に、ActiveXコントロールのインストール先ディレクトリは、Windows 95およびWindows NTのWindowsレジストレーション・データベースに登録され、開発環境でActiveXコントロールを参照できるようになります。

ActiveXコントロールを別のディレクトリに移動したり、ディレクトリ名を変更したりすると、レジストリの情報が無効になります。

ActiveXコントロールの移動やそのディレクトリ名の変更が必要な場合は、ほとんどのMicrosoft開発製品に付属しているregsrv32.exe または regActiveX32.exe ユーティリティを使って、ActiveXコントロールを新規の場所に再登録します。

 

移植性の問題 

ActiveXがサポートされるのは、Windowsプラットフォーム上のみです。ActiveXコントロールは、Web上またはUNIX上では使用できません。移植性が問題になる場合は、ActiveXコントロールを使用しないでください。 

ActiveXコールのデバッグ 

オブジェクト・タイプがコンパイル時にチェックされない場合は、そのオブジェクトのクラスに定義されていないオブジェクトに対してファンクションをコールすることができます。ファンクションは、名前ではなくIDにより結合されているため、意図していない別のファンクションがコールされて、異常なエラーが発生することがあります。

正しいメソッドのコールを保証する1つの方法は、ハードコードされた定数をGET_OLE_MEMBERIDのコールに置き換えて、生成されたファンクションを変更することです。例は次のとおりです。


Procedure Ole_Add(interface OleObj, TimeBegin VARCHAR2, TimeEnd VARCHAR2, Text VARCHAR2, BackColor OleVar := OleVar_Null) IS

BEGIN Init_OleArgs (4); Add_OleArg (TimeBegin); Add_OleArg (TimeEnd); Add_Olearg (Text); Add_OleArg (BackColor); Call_Ole (interface, 2); END ;

Call_ole()を次のように置き換えます。Call_Ole (interface, Get_Ole_MemberID(interface, 'Add'));

GET_OLE_MEMBERIDコールの後に、FORM_SUCCESSがあるかどうかをチェックできます。 

制限 

  • ActiveXイベント・プロシージャは制限されています。一般的に、同一のイベントが複数のアイテムに適用するためにGO_ITEMが必要である場合を除き、GO_ITEMをActiveXプロシージャ・コード内でコールすることはできません。ただし、同一イベントが複数項目に適用され、GO_ITEMが必要な場合は除きます。こうした場合には、On-Dispatchトリガー(ブロックまたはフォーム・レベル)において、DISPATCH_EVENT(RESTRICTED_ALLOWED)をコールすることにより、GO_ITEMビルトインを使用できます。注意: イベント・プロシージャはOn-Dispatchトリガー・コードに引き続いて自動的にコールされるため、明示的にコールする必要はありません。

  • ActiveXコントロール向けの初期化イベントはForms Runtimeでは起動しません。これらの初期化イベントは意図的に使用不可に設定されています。コントロールのネイティブ初期化イベントのかわりに、When-New-Item-InstanceまたはWhen-New-Record-Instanceを使用できます。

 
この項では、ActiveXコントロールを処理するためのガイドラインを提供します。

6.1.2.7 アプリケーションへのActiveXコントロールの追加

ActiveXコントロールをアプリケーションに追加する方法の詳細は、オンライン・ヘルプを参照してください。

6.1.2.8 ActiveXの例

この項では、ActiveXコントロールのスタート・ガイドとしていくつかの例を紹介します。

6.1.2.8.1 例1: ActiveX コントロール・プロパティの設定

Form Builderにおいて、:item('item_name').ocx.server_name.propertyバインド変数構文を使用して、AactiveXのプロパティ値を割り当てるか、または取り出すことができます。

例:

   :item('ActXitem').OCX.Spindial.spindialctrl.1.Needleposition:=
   :item('ActXitem').OCX.Spindial.spindialctrl.1.Needleposition + 1;

ActXitemは項目名、Spindial.spindialctrl.1はActiveXコントロール・サーバー名、Needlepositionはプロパティ名です。

system.cursor_itemがActiveXコントロールである場合は、次のコードも使用できます。

   :form.cursor_item.OCX.spindial.spindialctrl.1.Needlposition :=
   :form.cursor_item.OCX.spindial.spindialctrl.1.Needlposition + 1;
6.1.2.8.2 例2: ActiveX コントロール・プロパティの取得

Form Builderにおいて、プロパティ・アセサー・ファンクションおよびプロシージャを使用して、ActiveXプロパティを取得、設定できます。

例:

   tblname varchar2;
   tblname := table_pkg.TableName(:item('Oblk.Oitm').interface);

Table_pkgは、OLEインポータから作成されたプログラム単位の名前です。TableNameは、プロパティ・アセサー名です。Oblkは、ブロック名、Oitmは項目名です。

6.1.2.8.3 例3: ActiveXコントロール・メソッドのコール

この例では、SpreadTableパッケージ内のGetCellByColRowメソッドを使用してSpread Table ActiveXコントロールからセル値を取得します。

   DECLARE
      Cur_Row number;
      Cur_Col number;
      The_OLE_Obj OleObj;
   BEGIN
      Cur_Row:=SpreadTable.CurrentRow(:ITEM('BLK.ITM').interface);
      Cur_Col:=SpreadTable.CurrentCol(:ITEM('BLK.ITM').interface);
      The_OLE_Obj:=SpreadTable.GetCellByColRow(:ITEM('BLK.ITM').interface,
                                           Cur_Col, Cur_Row);
   END;

6.2 外部ファンクションを使用したアプリケーションのカスタマイズ

外部ファンクションを使用すると、アプリケーションをカスタマイズして機能を強化できます。

この項では、次のことを説明します。

6.2.1 外部ファンクション

外部ファンクションは3GLプログラミング言語で書かれたサブプログラムで、ユーザー固有の要件に合せてアプリケーションをカスタマイズできます。

外部ファンクションは、Oracleデータベース、Forms DeveloperおよびReports Developerの変数、項目、列およびパラメータとの対話に使用します。また、Windows DLLまたはAPIなどの外部定義ファンクションをコールすることもできます。

6.2.1.1 外部ファンクションを利用する場合

外部ファンクションは次の作業を行うためによく使用されます。

6.2.1.2 外部ファンクションのタイプ

3種類の外部ファンクションを開発できます。

6.2.1.2.1 Oracleプリコンパイラ外部ファンクション

Oracleプリコンパイラ外部ファンクションは最も一般的な外部ファンクションです。Oracleプリコンパイラを使用すると、Oracleデータベース、Forms DeveloperまたはReports Developerの変数、項目、列およびパラメータなどにアクセスする外部ファンクションを作成できます。

Oracleプリコンパイラ外部ファンクションには、Oracleプリコンパイラ・インタフェースが取り込まれます。このインタフェースにより、埋込みSQLコマンドを使用して、次のサポートされたホスト言語のいずれかでプログラムを作成できます。Ada、C、COBOL、FORTRAN、PascalおよびPL/I。

Oracleプリコンパイラ外部ファンクションのソース・ファイルには、埋込みSQL文を使用したホスト・プログラミング言語文およびOracleプリコンパイラ文が含まれています。Oracleプリコンパイラ外部ファンクションをプリコンパイルすると、埋込みSQL文は等価のホスト・プログラミング言語文に置換されます。プリコンパイルにより、ホスト言語コンパイラでコンパイルできるソース・ファイルができます。

6.2.1.2.2 Oracleコール・インタフェース(OCI)外部ファンクション

OCI外部ファンクションには、Oracleコール・インタフェースが取り込まれます。このインタフェースにより、Oracleデータベースのコールを含むサブプログラムを作成できます。OCIのみが取り込まれた(Oracleプリコンパイラ・インタフェースは取り込まれない)外部ファンクションでは、Forms DeveloperまたはReports Developerの変数、項目、列、パラメータにアクセスできません。

注意: Oracleプリコンパイラ・インタフェースとOCIの両方を組み合せた外部ファンクションを開発することもできます。

6.2.1.2.3 Oracle以外の外部ファンクション

Oracle以外の外部ファンクションには、Oracleプリコンパイラ・インタフェースも、OCIも取り込まれません。たとえば、Oracle以外の外部ファンクションは、すべてC言語のみで作成されることもあります。オラクル以外の外部ファンクションでは、Oracleデータベースをはじめ、Forms DeveloperまたはReports Developerの変数、項目、列、パラメータのいずれにもアクセスできません。

6.2.2 外部ファンクションのインタフェース

Forms DeveloperおよびReports Developerでは、プログラミング言語としてPL/SQLを使用します。Windows DLLのCファンクションなどの外部ファンクションをコールするには、PL/SQLに外部ファンクションとの通信インタフェースが必要です。

外部ファンクションとの通信には、Oracle外部ファンクション・インタフェース(ORA_FFI)またはユーザー・イグジット・インタフェースという2つの固有のインタフェースが使用できます。

6.2.2.1 Oracle外部ファンクション・インタフェース(ORA_FFI)

ORA_FFIは、Forms DeveloperおよびReports DeveloperでPL/SQLプログラムから3GLルーチンをコールするための移植性のある汎用メカニズムです。

PL/SQLインタフェースから起動する外部ファンクションは、ダイナミック・ライブラリに含まれている必要があります。ダイナミック・ライブラリの例としては、Microsoft Windowsのダイナミック・リンク・ライブラリやUNIXシステムの共有ライブラリがあります。

6.2.2.2 外部ファンクションへのユーザー・イグジット・インタフェース

ユーザー・イグジット・インタフェースは、Forms DeveloperおよびReports DeveloperでPL/SQLサブプログラムから3GLルーチンをコールするためのプラットフォーム固有のメカニズムです。

ユーザー・イグジット・インタフェースから起動する外部ファンクションは、ダイナミック・リンク・ライブラリ(.DLL)に含まれているか、または実行可能なアプリケーションにリンクされている必要があります。

6.2.2.3 ORA_FFIとユーザー・イグジットとの比較

この項では、ORA_FFIおよびユーザー・イグジットを使用する場合の長所と短所を説明します。

外部ファンクション  長所  短所 

ユーザー・イグジット 

  • ユーザー・イグジットは実行プログラムにリンクされています。この“緊密な結び付き”により、現行のデータベース接続を利用できます。

 
  • ユーザー・イグジットを使用する上で最も重大な短所は、メンテナンス上の負担です。ユーザー・イグジットの変更やForms DeveloperまたはReports Developerのアップグレードを行ったら、その都度ユーザー・イグジットを再リンクする必要があります。

  • ユーザー・イグジットは汎用ではありません。プラットフォーム固有です。

 

ORA_FFI 

  • ORA_FFIは、純粋なPL/SQL仕様部です。ORA_FFI仕様部は、Forms DeveloperまたはReports Developerコンポーネント内ではなく、ライブラリ(.PLLファイル)内に存在します。Forms DeveloperまたはReports Developerのアップグレードや外部ファンクションの変更を行っても、PLLファイルを変更したり、再生成する必要はありません。

  • ORA_FFIは汎用です。

  • Forms DeveloperおよびReports Developerには、すでに使用可能なライブラリ(Windows APIファンクション)へのアクセスを可能にするORA_FFIパッケージ(D2KWUTIL.PLL)が複数用意されています。

 
  • OAR_FFIを使用しながら、Pro*Cで独自の外部コード・モジュールを作成している場合は、現行のオープン・データベース接続を使用できません。2番目の接続をオープンする必要があります。

  • 構造体や配列などの複雑なデータ型を渡すことはできません。たとえば、EXEC TOOLS GETまたはEXEC TOOLS PUTを使用して、Forms DeveloperまたはReports Developerインタフェースとデータをやりとりすることはできません。

 

6.2.3 外部ファンクションのガイドライン

この項では、外部ファンクションを処理するためのガイドラインを提供します。

項目  推奨事項 

どの外部ファンクション・インタフェースを使用しますか? 

Oracle外部ファンクション・インタフェース(ORA_FFI)を使用します。ORA_FFIは、移植性のある汎用インタフェースで、メンテナンスはほとんど、またはまったく必要ありません。 

外部ファンクションから画面I/Oを実行できますか? 

外部ファンクションからホスト言語の画面I/Oを実行しないでください。この制限が存在するのは、画面I/Oを実行するためにホスト言語が使用するランタイム・ルーチンと、画面I/Oを実行するためにForms DeveloperおよびReports Developerが使用するルーチンが競合するためです。ただし、外部ファンクションからホスト言語によるファイルI/Oを実行することはできます。 

ユーザー・イグジットを作成するためにどのホスト言語を使用しますか? 

どのホスト言語を使用するかは好みの問題です。しかし、C言語をお薦めします。

注意: C言語のランタイム・ファンクションの中には、.DLLファイルで使用できないものがあります。詳細は、使用しているコンパイラのマニュアルを参照してください。 

ユーザー・イグジットをプリコンパイルするためにどのプリコンパイラを使用しますか? 

Pro*Cバージョン2.2.4/8.0.4を使用します。

プリコンパイル時に、次のMSVCコンパイラ・フラグを必ず指定します。

Large, Segment Setup:SS != DS, DSloads on function entry

Assume 'extern' and Uninitialized Data 'far' is checked Yes

In Windows Prolog/Epilogue, Generate prolog/Epilogue for None 

Forms DeveloperまたはReports Developerの以前のバージョンからのアップグレード時に、ユーザー・イグジットを再コンパイルする必要がありますか? 

はい。特に、それぞれ別のユーザー・イグジット・セットを持つ実行プログラムが複数ある場合、メンテナンス上の負担が発生します。

ユーザー・イグジットの変更時、あるいはForms DeveloperまたはReports Developerのアップグレード時には、ユーザー・イグジットをForms DeveloperアプリケーションまたはReports Developerアプリケーションに再リンクする必要があります。 

外部ファンクションをWeb上で利用できますか? 

ORA_FFIおよびユーザー・イグジットはWeb上で機能しません。Web上で利用する場合、外部ファンクションは、ブラウザ側ではなく、サーバー側のDLLとインタフェースします。 

外部ファンクションの詳細は、次の出版物を参照してください。

Oracleプリコンパイラ・インタフェース 

Oracleプリコンパイラに応じたプリコンパイラ・プログラマーズ・ガイド 

ホスト言語のサポート 

使用しているオペレーティング・システム固有のOracleインストレーション・ガイド 

外部ファンクション処理時のオペレーティング・システム固有の要件 

オンライン・ヘルプ 

OCI 

『Oracle8コール・インタフェース・プログラマーズ・ガイド』 

DLLの作成 

オンライン・ヘルプと使用しているコンパイラのマニュアル 

ORA_FFI 

オンライン・ヘルプ 

ユーザー・イグジット 

オンライン・ヘルプ 

PL/SQL  

『PL/SQLユーザーズ・ガイド』またはオンライン・ヘルプ 

6.2.4 外部ファンクションの作成

この項では、外部ファンクションのインタフェースを作成するための詳細な手順を説明します。

6.2.4.1 外部ファンクションへのORA_FFIインタフェースの作成

次の例では、WinSampleという名前のPL/SQLパッケージを作成します。WinSampleパッケージには、ダイナミック・ライブラリKRNL386.EXEにある外部ファンクションGetPrivateProfileStringへのインタフェースが含まれています。

注意: 外部ファンクションへのORA_FFIインタフェースを作成する場合は、2つの基本的な手順を実行します。第一に、サブプログラムを作成し、外部ファンクション(ディスパッチャ・ファンクション)に関連付けます。PL/SQLサブプログラムを外部ファンクションに対応付けることにより、対応付けられたPL/SQLサブプログラムをコールするたびに、外部ファンクションを起動することができます。外部ファンクションとPL/SQLサブプログラムとの対応付けが必要な理由は、Forms DeveloperおよびReports DeveloperでPL/SQL構成体が使用されるためです。第二に、引数をディスパッチャ・ファンクションに渡すPL/SQLファンクションを作成します。ディスパッチャ・ファンクションは外部ファンクションを起動します。

  1. パッケージ仕様部を作成します。

    パッケージ仕様部はライブラリを表している必要があります。また、起動しようとするPL/SQLファンクションを定義する必要があります。

    例:

    	PACKAGE WinSample IS
    	FUNCTION GetPrivateProfileString 
    	(Section 	IN  VARCHAR2,
    	Entry 	IN  VARCHAR2,
    	DefaultStr 	IN  VARCHAR2,
    	ReturnBuf 	IN  OUT VARCHAR2,
    	BufLen 	IN  PLS_INTEGER,
    	Filename 	IN  VARCHAR2)
    	RETURN PLS_INTEGER;
    	END;
    

    この例では、WinSample.GetPrivateProfileString PL/SQLファンクションを呼び出して、ダイナミック・ライブラリKRNL386.EXEにあるGetPrivateProfileString 外部ファンクションを起動します。

    注意: CファンクションGetPrivateProfileStringのパラメータをチェックして、一致するPL/SQLパラメータ型とPL/SQL戻り型を指定します。Cデータ型intは、PL/SQLパラメータIN PLS_INTEGERおよびPL/SQL戻り型PLS_INTEGERと等価です。Cデータ型charは、PL/SQLパラメータIN VARCHAR2と等価です。

  1. ライブラリとファンクション・ハンドルを定義します。

    例:

    	PACKAGE BODY WinSample IS
    	lh_KRNL386 ORA_FFI.LIBHANDLETYPE;
    	fh_GetPrivateProfileString ORA_FFI.FUNCHANDLETYPE;
    

    この手順において、ライブラリおよびファンクションのハンドル型を宣言します。後で、ORA_FFI.LOAD_LIBRARYおよびORA_FFI.REGISTER_FUNCTIONを使用してライブラリをロードして、ファンクションを登録します。これらのファンクションはそれぞれ、指定したライブラリおよびファンクションにハンドル(ポインタ)を戻します。ORA_FFI.LIBHANDLETYPEおよびORA_FFI.FUNCHANDLETYPEは、これらのハンドルのPL/SQLデータ型です。

  1. ディスパッチャ・ファンクションを作成します。ディスパッチャ・ファンクションは外部ファンクションを起動します。

    例:

    	FUNCTION i_GetPrivateProfileString
    	(funcHandle IN ORA_FFI.FUNCHANDLETYPE,
    	Section IN OUT VARCHAR2,
    	Entry 	IN OUT VARCHAR2,
    	DefaultStr 	IN OUT VARCHAR2,
    	ReturnBuf 	IN OUT VARCHAR2,
    	BufLen 	IN PLS_INTEGER,
    	Filename 	IN OUT VARCHAR2)
    	RETURN PLS_INTEGER;
    	PRAGMA INTERFACE(C,i_GetPrivateProfileString,11265);
    

    外部ファンクションをコールするディスパッチャ・ファンクションの最初の引数には、少なくとも1つのパラメータが必要です。また、最初のパラメータは、サブプログラムが起動する登録された外部ファンクションのハンドルである必要があります。

    ディスパッチャ・ファンクションをPL/SQLファンクションからコールする場合は、手順2(fh_GetPrivateProfileString)での定義に従ってファンクション・ハンドルを渡します。

    ディスパッチャ・ファンクションのコール時に、PRAGMA文は、ダイナミック・ライブラリと通信するメモリー位置(前述のコードで指定した11265)に制御を渡します。

  1. ディスパッチャ・ファンクションを呼び出すPL/SQLファンクションを作成します。このPL/SQLファンクションは、パッケージ仕様部で定義したファンクション(手順1)です。

    例:

    	FUNCTION GetPrivateProfileString
    	(Section IN  VARCHAR2,
    	Entry IN  VARCHAR2,
    	DefaultStr IN  VARCHAR2,
    	ReturnBuf IN  OUT VARCHAR2,
    	BufLen IN  PLS_INTEGER,
    	Filename IN  VARCHAR2)
    	RETURN PLS_INTEGER IS 
    	Section_l VARCHAR2(512)   := Section;
    	Entry_l VARCHAR2(512)   := Entry;
    	DefaultStr_l VARCHAR2(512)   := DefaultStr;
    	ReturnBuf_l VARCHAR2(512)   := RPAD(SUBSTR(NVL
    	(ReturnBuf,' '),1,512),512,CHR(0));
    	BufLen_l PLS_INTEGER   := BufLen;
    	Filename_l VARCHAR2(512)   := Filename;
    	rc PLS_INTEGER;
    	BEGIN 
    		rc  := i_GetPrivateProfileString
    	(fh_GetPrivateProfileString,
    	Section_l,
    	Entry_l,
    	DefaultStr_l,
    	ReturnBuf_l,
    	BufLen_l,
    	Filename_l);
    	ReturnBuf := ReturnBuf_l;
    	RETURN (rc);
    	END;
    

    これは、アプリケーションからコールするPL/SQLファンクションです。このファンクションが引数をディスパッチャ・ファンクションi_GetPrivateProfileStringに渡すと、i_GetPrivateProfileStringKRNL386.EXEにあるCファンクションGetPrivateProfileStringを起動します。ディスパッチャ・ファンクションの最初の引数はファンクション・ハンドルでなければならないことを思い出してください。ここで、fh_GetPrivateProfileStringは、手順2で宣言されているファンクション・ハンドルを渡すために使用されます。

  1. パッケージ本体を作成します。

    パッケージ本体では、外部ファンクションを初期化するために、次の4つの手順が実行される必要があります。

    • ライブラリをロードします。

    • ライブラリにあるファンクションを登録します。

    • パラメータを登録します(ある場合)。

    • 戻り値の型を登録します(ある場合)。

    例:

    	BEGIN 
    	/* Load the library .*/
     	lh_KRNL386 := ORA_FFI.LOAD_LIBRARY
    	('location of the DLL here','KRNL386.EXE');
    		
    	/* Register the foreign function. */
    	fh_GetPrivateProfileString := ORA_FFI.REGISTER_FUNCTION (lh_
    	KRNL386,'GetPrivateProfileString',ORA_FFI.PASCAL_STD);
         		
    	/* Register the parameters. */
    	ORA_FFI.REGISTER_PARAMETER
    	(fh_GetPrivateProfileString,ORA_FFI.C_CHAR_PTR); ORA_FFI.REGISTER_PARAMETER
    	(fh_GetPrivateProfileString,ORA_FFI.C_CHAR_PTR); ORA_FFI.REGISTER_PARAMETER
    	(fh_GetPrivateProfileString,ORA_FFI.C_CHAR_PTR); ORA_FFI.REGISTER_PARAMETER
    	(fh_GetPrivateProfileString,ORA_FFI.C_CHAR_PTR);
    	ORA_FFI.REGISTER_PARAMETER
    	(fh_GetPrivateProfileString,ORA_FFI.C_INT); 	ORA_FFI.REGISTER_PARAMETER
    	(fh_GetPrivateProfileString,ORA_FFI.C_CHAR_PTR);
         		
    	/* Register the return type. */
    	ORA_FFI.REGISTER_RETURN(fh_GetPrivateProfileString,ORA_FFI.C_INT);
    	END WinSample;
    

    手順2において、ライブラリおよびファンクションに対して2つのハンドルを宣言したことを思い出してください。この手順において、ORA_FFI.LOAD_LIBRARYおよびORA_FFI.REGISTER_FUNCTIONファンクションを使用して、ハンドルに値を割り当てます。

    ORA_FFI.LOAD_LIBRARYは、2つの引数を取ります。ダイナミック・ライブラリの位置と名前です。ORA_FFI.REGISTER_FUNCTIONは、3つの引数を取り出します。ファンクションが含まれるライブラリのライブラリ・ハンドル、ファンクション名、コール標準です。コール標準は、C_STD(Cコール標準の場合)またはPASCAL_STD(Pascalコール標準の場合)のいずれかです。

    ライブラリのロードおよびファンクションの登録後に、パラメータおよび戻り値の型(ある場合)を登録する必要があります。

    ORA_FFI.REGISTER_PARAMETERORA_FFI.REGISTER_RETURN はそれぞれ2つの引数を取ります。ファンクション・ハンドルおよび引数型です。

  1. Forms DeveloperまたはReports Developerを使用してパッケージが含まれるライブラリ・ファイル(.PLL)を作成し、それをアプリケーションに連結します。

  1. アプリケーションから外部ファンクションをコールします。

    例:

    	x := Winsample.GetPrivateProfileString
    	('Oracle', 'ORACLE_HOME', '<Not Set>', 'Value', 100, 'oracle.ini');
    

    6.2.4.2 外部ファンクションへのユーザー・イグジット・インタフェースの作成

    ユーザー・イグジットは汎用ではありません。プラットフォーム固有です。ユーザー・イグジットのインプリメントの詳細の中には、各オペレーティング・システムに固有のものがあります。次の例では、Windows 95におけるユーザー・イグジットの作成方法について説明します。

    Microsoft Windowsでは、ユーザー・イグジットから起動する外部ファンクションは、ダイナミック・リンク・ライブラリ(.DLL)に含まれています。DLLは、含まれているコードが起動されたときにのみメモリーにロードされるライブラリです。

    6.2.4.2.1 例: Windows 95でのユーザー・イグジットの作成

    次の例では、ID列をEMP表に追加する外部ファンクションを作成します。

    この例では、次に示す複数のサンプル・ファイルを使用します。

    • UE_SAMP.MAK は、IAPXTBコントロール構造体を含むプロジェクト・ファイルです。このプロジェクトを作成すると、UE_SAMP.DLLが生成されます。

    • IFXTB60.DLL は、ユーザー・イグジット・インタフェースから起動する外部ファンクションを含むデフォルト・ファイルです。このファイルは、Form Builderに付属するDLLファイルで、当初はユーザ定義の外部ファンクションを含んでいません。このファイルは、インストール時にORACLE_HOME\BIN ディレクトリに配置されます。新規の外部ファンクションの作成時には、既存のIFXTB60.DLLファイルを新規のIFXTB60.DLLと置き換えてください。

    • UE_XTB.Cは、IAPXTBコントロール構造体を作成するためのテンプレート・ソース・ファイルです。UE_XTB.Cには、IAPXTBコントロール構造体のエントリの例が含まれています。このファイルを変更し、外部ファンクション・エントリを追加します。

    • UE.Hは、IAPXTB構造体の定義に使用されるサンプル・ヘッダー・ファイルです。

    • IFXTB60.DEF には、独自のDLLを作成するために必要な定義が含まれています。IFXTB60.DEFを使用して、外部ファンクションをエクスポートします。IFXTB60.DEFには複数のエクスポート文が含まれています。これらのエクスポート文は、ユーザー・イグジット・インタフェースにアクセスするためにForm Builderで使用されますので、変更しないでください。

    • UEZ.OBJ は、独自の.OBJファイルにリンクする.OBJファイルです。

    ユーザー・イグジットのサンプル・ファイルは、ORACLE_HOMEディレクトリ(たとえば、 C:\ORAWIN95\FORMS60\USEREXIT)にあります。

    1. 外部ファンクションを作成します。

      たとえば、テキスト・ファイルUEXIT.PCを作成してから、次を追加します。

      /* UEXIT.PC file */  
      /* This foreign function adds an ID column to the EMP table. */ 	
      #ifndef UE	
      #include "ue.h"	   
      #endif		
      #ifndef _WINDLL   	
      #define SQLCA_STORAGE_CLASS  extern	   
      #endif		   
      EXEC SQL INCLUDE sqlca.h	;   
      void  AddColumn() {	   
      EXEC SQL alter table EMP add ID varchar(9);	   
      }
      
    1. Pro*Cプリコンパイラで外部ファンクションをプリコンパイルます。

      たとえば、Pro*Cを使用してUEXIT.PCファイルをプリコンパイルします。UEXIT.PCをプリコンパイルすると、Pro*Cでは、UEXIT.Cという名前のCファイルが作成されます。

      注意: プリコンパイル時に、次のMSVCコンパイラ・フラグを必ず指定します。

      Large, Segment Setup:SS != DS, DSloads on function entry

      Assume 'extern' and Uninitialized Data 'far' is checked Yes

      In Windows Prolog/Epilogue, Generate prolog/Epilogue for None

    2. ヘッダー・ファイルを作成します。

      ヘッダー・ファイルは、外部ファンクションを定義する必要があります。

      たとえば、次の行を追加して、サンプル・ヘッダー・ファイルUE.Hを変更します。

      extern   void   AddColumn();
      
      1. IAPXTBコントロール構造体を作成します。

        たとえば、UE.Hのインクルード文UE.H (# include "ue.h")、ユーザー・イグジット名(Add_ID_Column)、外部ファンクション名(AddColumn)、および言語タイプ(XITCC)を追加して、サンプル・ファイルUE_XTB.Cを変更します。

        #ifndef UE
        #include "ue.h"
        #endif /* UE */
        #include "ue_samp.h"
        /* Define the user exit table */
        exitr iapxtb[] =  {  /* Holds exit routine pointers */
             "Add_ID_Column", AddColumn, XITCC,
             (char *) 0, 0, 0         /* zero entry marks the end */
        }; /* end iapxtb */
        
        1. DLLファイルを作成します。DLLファイル作成の手順は、使用しているコンパイラによって異なります。詳細は、使用しているコンパイラのマニュアルを参照してください。

          例えば、コンパイラを使用して、次のものを含むプロジェクトを作成します。UE_SAMP.MAK、IFXTB60.DEFUEZ.OBJUE_XTB.CおよびUEXIT.C

          DLLを作成する前に、次のファイルをリンクする必要があります。

          LIBC.LIB	       
          OLDNAMES	
          C:\ORAWIN95\FORMS60\USEREXIT\IFR60.LIB	
          C:\ORAWIN95\PRO20\USEREXIT\SQLLIB18.LIB
          C:\ORAWIN95\PRO20\USEREXIT\SQXLIB18.LIB
          

            UE_SAMP.MAKプロジェクトを作成すると、UE_SAMP.DLL.という名前のDLLファイルが作成されます。UE_SAMP.DLLエントリを、レジストリのFORMS60_USEREXITSパラメータで定義されているDLLリストに追加します。

            UE_SAMP.DLLをIFXTB60.DLLに改名し、C:\ORAWIN95\BINディレクトリにあるIFXTB60.DLLをバックアップし、新規のIFXTB60.DLLC:\ORAWIN95\BINディレクトリにコピーすることもできます。

        1. 外部ファンクションをユーザー・イグジットから起動します。

          たとえば、ユーザー・イグジットから外部ファンクションを呼び出すWhen-Button-Pressedトリガーを作成します。

          次の文では、USER_EXITビルトインにあるユーザー・イグジット名Add_ID_Columnを指定して、AddColumn外部ファンクションを起動する方法を示します。

          /* Trigger:  When-Button-Pressed */	
          USER_EXIT('Add_ID_Column');
          

        6.2.5 外部ファンクションの例

        この項では、複数の例を示しながら外部ファンクションの使用方法を説明します。

        6.2.5.1 WindowsヘルプをコールするORA_FFIの使用

        /* WinHelp ORA_FFI.                                                         */  
        /*                                                                          */  
        /*                                                                          */  
        /* Usage: WinHelp.WinHelp(helpfile VARCHAR2,                                */  
        /*                        command  VARCHAR2,                                */  
        /*                        data    {VARCHAR2/PLS_INTEGER See Below})         */  
        /*                                                                          */  
        /*        command can be one of the following:                              */  
        /*                                                                          */  
        /*            'HELP_INDEX'         Help Contents                            */  
        /*            'HELP_CONTENTS'            "                                  */  
        /*            'HELP_CONTEXT'       Context Key  (See below)                 */  
        /*            'HELP_KEY'           Key Search                               */  
        /*            'HELP_PARTIALKEY'    Partial Key Search                       */  
        /*            'HELP_QUIT'          Quit                                     */  
        /*                                                                          */  
        /*        data contains a string for the key search or a numeric context    */  
        /*        value if using topics.                                            */  
        /*                                                                          */  
        /* Winhelp.Winhelp('C:\ORAWIN95\TOOLS\DOC60\US\IF60.HLP',                     */  
        /*                     'HELP_PARTIALKEY',                                   */  
        /*                     'ORA_FFI');                                          */  
        /*                                                                          */  
        /* The commented sections replace the line below if using HELP_CONTEXT keys */  
          
        PACKAGE WinHelp IS   
          FUNCTION WinHelp(helpfile IN VARCHAR2,  
                           command  IN VARCHAR2,  
                           data     IN VARCHAR2)  
                           RETURN PLS_INTEGER;  
        END;  
          
        PACKAGE BODY WinHelp IS   
          lh_USER ora_ffi.libHandleType;  
          fh_WinHelp ora_ffi.funcHandleType;  
          
          FUNCTION i_WinHelp(funcHandle IN ora_ffi.funcHandleType,  
                             hwnd       IN PLS_INTEGER,  
                             helpfile   IN OUT VARCHAR2,  
                             command    IN PLS_INTEGER,  
                             data       IN OUT VARCHAR2)  
                             RETURN PLS_INTEGER;  
          
          PRAGMA INTERFACE(C,i_WinHelp,11265);  
          
          FUNCTION WinHelp(helpfile IN VARCHAR2,  
                           command  IN VARCHAR2,  
                           data     IN VARCHAR2)  
                           RETURN PLS_INTEGER   
          IS   
            hwnd_l     PLS_INTEGER;  
            helpfile_l VARCHAR2(512) := helpfile;  
            command_l  PLS_INTEGER;  
            data_l     VARCHAR2(512) := data;  
            rc         PLS_INTEGER;  
          
            FUNCTION Help_Convert(command IN VARCHAR2)  
                                  RETURN PLS_INTEGER  
            IS  
            BEGIN  
              /* The windows.h definitions for command */  
          
              /* HELP_CONTEXT      0x0001 */  
              /* HELP_QUIT         0x0002 */  
              /* HELP_INDEX        0x0003 */  
              /* HELP_CONTENTS     0x0003 */  
              /* HELP_HELPONHELP   0x0004 */  
              /* HELP_SETINDEX     0x0005 */  
              /* HELP_SETCONTENTS  0x0005 */  
              /* HELP_CONTEXTPOPUP 0x0008 */  
              /* HELP_FORCEFILE    0x0009 */  
              /* HELP_KEY          0x0101 */  
              /* HELP_COMMAND      0x0102 */  
              /* HELP_PARTIALKEY   0x0105 */  
              /* HELP_MULTIKEY     0x0201 */  
              /* HELP_SETWINPOS    0x0203 */  
               
              if command = 'HELP_CONTEXT'    then return(1);   end if;   
              if command = 'HELP_KEY'        then return(257); end if;  
              if command = 'HELP_PARTIALKEY' then return(261); end if;  
              if command = 'HELP_QUIT'       then return(2);   end if;  
              /* If nothing else go to the contents page */  
              return(3);      
            END;  
          
          BEGIN   
            hwnd_l :=  
            TO_PLS_INTEGER(Get_Item_Property(name_in('SYSTEM.CURSOR_ITEM'),WINDOW_HANDLE));
            
            command_l := Help_Convert(command);  
          
            rc  := i_WinHelp(fh_WinHelp,  
                             hwnd_l,  
                             helpfile_l,  
                             command_l,  
                             data_l);  
          
            RETURN (rc);  
          END ;  
          
        BEGIN   
          BEGIN   
            lh_USER := ora_ffi.find_library('USER.EXE');  
            EXCEPTION WHEN ora_ffi.FFI_ERROR THEN   
            lh_USER := ora_ffi.load_library(NULL,'USER.EXE');  
          END ;  
          
          fh_WinHelp :=  
        ora_ffi.register_function(lh_USER,'WinHelp',ora_ffi.PASCAL_STD);
          
          ora_ffi.register_parameter(fh_WinHelp,ORA_FFI.C_INT);        /* HWND   */  
          ora_ffi.register_parameter(fh_WinHelp,ORA_FFI.C_CHAR_PTR);   /* LPCSTR */  
          ora_ffi.register_parameter(fh_WinHelp,ORA_FFI.C_INT);        /* UINT   */  
          ora_ffi.register_parameter(fh_WinHelp,ORA_FFI.C_CHAR_PTR);   /* DWORD  */  
          
          ora_ffi.register_return(fh_WinHelp,ORA_FFI.C_INT);           /* BOOL   */  
          
        END WinHelp; 
        

        6.2.5.2 Windowsでファイル・オープン・ダイアログを開くためのORA_FFIの使用

        
        PACKAGE OraDlg IS 
        FUNCTION OraMultiFileDlg
        (Title IN  VARCHAR2,
        Filter IN  VARCHAR2,
        Dir IN  VARCHAR2,
        FileString IN OUT VARCHAR2)
        RETURN PLS_INTEGER;
        FUNCTION OraSingleFileDlg
        (Title IN  VARCHAR2,
        Filter IN  VARCHAR2,
        Dir IN  VARCHAR2,
        FileString IN OUT VARCHAR2)
        RETURN PLS_INTEGER;
        END OraDlg;
        PACKAGE BODY OraDlg IS 
             lh_ORADLG ora_ffi.libHandleType;
        fh_OraMultiFileDlg ora_ffi.funcHandleType;
        fh_OraSingleFileDlg ora_ffi.funcHandleType;
        FUNCTION i_OraMultiFileDlg
        (funcHandle IN ora_ffi.funcHandleType,
        Title IN OUT VARCHAR2,
        Filter IN OUT VARCHAR2,
        Dir IN OUT VARCHAR2,
        FileString IN OUT VARCHAR2)
        RETURN PLS_INTEGER;
        PRAGMA INTERFACE(C,i_OraMultiFileDlg,11265);
        FUNCTION OraMultiFileDlg
        (Title IN  VARCHAR2,
        Filter IN  VARCHAR2,
        Dir IN  VARCHAR2,
        FileString IN OUT VARCHAR2)
        RETURN PLS_INTEGER IS 
        Title_l VARCHAR2(128)  :=  RPAD(SUBSTR(NVL(Title,'Open'),1,128),128,CHR(0));
        Filter_l VARCHAR2(128)  :=  RPAD(SUBSTR(NVL
        (Filter,'All Files (*.*)|*.*|'),1,128),128,CHR(0));
        Dir_l VARCHAR2(256)  :=  RPAD(SUBSTR(NVL(Dir,' '),1,256),256,CHR(0));
        FileString_l VARCHAR2(2000)  :=  RPAD(SUBSTR(NVL(FileString,' 
        '),1,2000),2000,CHR(0));
        rc PLS_INTEGER;
        BEGIN 
             rc  := i_OraMultiFileDlg(fh_OraMultiFileDlg,
        Title_l,
        Filter_l,
        Dir_l,
        FileString_l);
             FileString := FileString_l;
        RETURN (rc);
        END ;
        FUNCTION i_OraSingleFileDlg
        (funcHandle IN ora_ffi.funcHandleType,
        Title IN OUT VARCHAR2,
        Filter IN OUT VARCHAR2,
        Dir IN OUT VARCHAR2,
        FileString IN OUT VARCHAR2)
        RETURN PLS_INTEGER;
        PRAGMA INTERFACE(C,i_OraSingleFileDlg,11265);
        FUNCTION OraSingleFileDlg
        (Title IN  VARCHAR2,
        Filter IN  VARCHAR2,
        Dir IN  VARCHAR2,
        FileString IN OUT VARCHAR2)
        RETURN PLS_INTEGER IS 
        Title_l VARCHAR2(128)  :=  RPAD(SUBSTR(NVL(Title,'Open'),1,128),128,CHR(0));
        Filter_l VARCHAR2(128)  :=  RPAD(SUBSTR(NVL
        (Filter,'All Files (*.*)|*.*|'),1,128),128,CHR(0));
        Dir_l VARCHAR2(256)  :=  RPAD(SUBSTR(NVL(Dir,' '),1,256),256,CHR(0));
        FileString_l VARCHAR2(2000)  :=  RPAD(SUBSTR(NVL(FileString,' 
        '),1,2000),2000,CHR(0));
        rc PLS_INTEGER;
        BEGIN 
             rc  := i_OraSingleFileDlg(fh_OraSingleFileDlg,
        Title_l,
        Filter_l,
        Dir_l,
        FileString_l);
             FileString := FileString_l;
        RETURN (rc);
        END ;
        BEGIN 
             BEGIN 
             lh_ORADLG := ora_ffi.find_library('ORADLG.DLL');
             EXCEPTION WHEN ora_ffi.FFI_ERROR THEN 
             lh_ORADLG := ora_ffi.load_library(NULL,'ORADLG.DLL');
             END ;
             fh_OraMultiFileDlg := ora_ffi.register_function
        (lh_ORADLG,'OraMultiFileDlg',ora_ffi.PASCAL_STD);
             ora_ffi.register_parameter(fh_OraMultiFileDlg,ORA_FFI.C_CHAR_PTR);
             ora_ffi.register_parameter(fh_OraMultiFileDlg,ORA_FFI.C_CHAR_PTR);
             ora_ffi.register_parameter(fh_OraMultiFileDlg,ORA_FFI.C_CHAR_PTR);
             ora_ffi.register_parameter(fh_OraMultiFileDlg,ORA_FFI.C_CHAR_PTR);
             ora_ffi.register_return(fh_OraMultiFileDlg,ORA_FFI.C_LONG);
             fh_OraSingleFileDlg := ora_ffi.register_function
        (lh_ORADLG,'OraSingleFileDlg',ora_ffi.PASCAL_STD);
             ora_ffi.register_parameter(fh_OraSingleFileDlg,ORA_FFI.C_CHAR_PTR);
             ora_ffi.register_parameter(fh_OraSingleFileDlg,ORA_FFI.C_CHAR_PTR);
             ora_ffi.register_parameter(fh_OraSingleFileDlg,ORA_FFI.C_CHAR_PTR);
             ora_ffi.register_parameter(fh_OraSingleFileDlg,ORA_FFI.C_CHAR_PTR);
             ora_ffi.register_return(fh_OraSingleFileDlg,ORA_FFI.C_LONG);
        END OraDlg;
        

        6.2.5.3 STDIN/STDOUT型インタフェースでUNIX(SUN)実行プログラムをコールするためのORA_FFIの使用

        /* Copyright (c) 1997 by Oracle Corporation */ 
        /* 
           NAME 
             ora_pipe_io_spec.sql - Specification for access to Unix Pipe mechanism 
           DESCRIPTION 
             Demonstration of how to use the ORA_FFI Package to provide access to the 
             Unix Pipe C functions. 
           PUBLIC FUNCTION(S) 
             popen    - Open the Pipe command 
             get_line - Get a line of Text from a Pipe 
             put_line - Put a line of Text into a Pipe 
             pclose   - Close the Pipe 
             is_open  - Determine whether the Pipe descriptor is open. 
           NOTES 
         
             In Order to use these routines you could write  the following 
             PL/SQL Code: 
         
                -- Example of Calls to ora_pipe_io functions 
                DECLARE 
                    stream ora_pipe_io.PIPE; 
                    buffer VARCHAR2(240); 
                BEGIN 
                    stream := ora_pipe_io.popen('ls -l', ora_pipe_io.READ_MODE); 
         
                    loop 
                        exit when not ora_pipe_io.get_line(stream, buffer, 240); 
                        :directory.file := buffer; 
                        down; 
                    end loop; 
             
                    ora_pipe_io.pclose(stream); 
                END; 
         
           MODIFIED   (MM/DD/YY) 
            smclark    08/05/94 -  Creation 
        */ 
         
        PACKAGE ora_pipe_io is 
         
            /* 
            ** Arguments to popen. 
            */ 
            READ_MODE constant VARCHAR2(1) := 'r'; 
            WRITE_MODE constant VARCHAR2(1) := 'w'; 
         
            /* ------------- TYPE PIPE ----------- */ 
            /* 
            ** Public Type PIPE - Handle to a Un*x pipe 
            ** 
            ** Do not modify the private members of this type 
            */ 
            TYPE PIPE is RECORD 
                (file_handle ORA_FFI.POINTERTYPE, 
                 is_open boolean, 
                 read_write_mode VARCHAR2(1)); 
         
         
            /* ------------ FUNCTION POPEN ----------- */ 
            /* 
            ** Function POPEN -- Open a Un*x pipe command 
            ** 
            ** Given a Unix command to execute and a Pipe read/write mode in which 
            ** to execute the instruction this Function will execute the Command 
            ** and return a handle, of type PIPE, to the resulting Input/Output 
            ** stream. 
            ** 
            ** The command to be executed is limited to 1024 characters. 
            */ 
            FUNCTION popen(command in VARCHAR2, 
                           ctype in VARCHAR2) 
            RETURN PIPE; 
         
         
            /* ------------ PROCEDURE PCLOSE ----------- */ 
            /* 
            ** Procedure PCLOSE -- Close a pipe 
            ** 
            ** Close a previously opened pipe. 
            ** 
            ** Raises a VALUE_ERROR exception if incorrect arguments are passed. 
            */ 
            PROCEDURE pclose(stream in out PIPE); 
         
         
            /* ------------ FUNCTION GET_LINE ----------- */ 
            /* 
            ** Function GET_LINE 
            ** -- Get a line of text into a buffer from the read mode pipe. 
            ** 
            ** Get a line of text from a previously opened pipe. 
            ** 
            ** Raises a VALUE_ERROR exception if incorrect arguments are passed.  
            ** For example 
            ** if you pass a pipe which has never been opened (using popen) 
            */ 
            FUNCTION get_line(stream in out PIPE, 
                              s in out VARCHAR2, 
                              n in PLS_INTEGER) 
            RETURN BOOLEAN; 
         
         
            /* ------------ PROCEDURE PUT_LINE ----------- */ 
            /* 
            ** Procedure PUT_LINE -- Put a line of text into a a write mode pipe. 
            ** 
            ** Put a line of text into a previously opened pipe. 
            ** 
            ** Raises a VALUE_ERROR exception if incorrect arguments are passed.  
            ** For example 
            ** if you pass a pipe which has never been opened (using popen) 
            ** 
            ** The Internal buffer for the string to write is limited to 2048 bytes 
            */ 
            PROCEDURE put_line(stream in out PIPE, 
                               s in VARCHAR2); 
         
         
            /* ------------ FUNCTION IS_OPEN ----------- */ 
            /* 
            ** Function IS_OPEN -- Determines whether a pipe is open. 
            ** 
            ** Returns TRUE if the pipe is open, FALSE if the pipe is closed. 
            */ 
            FUNCTION is_open(stream in PIPE) 
            RETURN BOOLEAN; 
        END; 
         
        /*    ora_pipe_io_body.sql - Body of Package for access to Unix Pipe mechanism 
           DESCRIPTION 
             Demonstration of how to use the ORA_FFI Package to provide access to the 
             Unix Pipe C functions. 
           PUBLIC FUNCTION(S) 
             popen    - Open the Pipe command 
             get_line - Get a line of Text from a Pipe 
             put_line - Put a line of Text into a Pipe 
             pclose   - Close the Pipe 
             is_open  - Determine whether the Pipe descriptor is open. 
           PRIVATE FUNCTION(S) 
             icd_popen, icd_fgets, icd_fputs, icd_pclose 
           NOTES 
           MODIFIED   (MM/DD/YY) 
            smclark    11/02/94 -  Modified for production release changes to ORA_FFI. 
            smclark    08/05/94 -  Creation 
        */ 
         
         PACKAGE BODY ora_pipe_io is 
            lh_libc   ora_ffi.libHandleType; 
            fh_popen  ora_ffi.funcHandleType; 
            fh_pclose ora_ffi.funcHandleType; 
            fh_fgets  ora_ffi.funcHandleType; 
            fh_fputs  ora_ffi.funcHandleType; 
         
            /* ------------ FUNCTION ICD_POPEN ----------- */ 
            /* 
            ** Function ICD_POPEN -- Interface routine to C function popen 
            ** 
            ** This function acts as the interface to the popen function in 
            ** libc. 
            */ 
            FUNCTION icd_popen(funcHandle in ora_ffi.funcHandleType, 
                               command in out VARCHAR2, 
                               ctype in out VARCHAR2) 
            return ORA_FFI.POINTERTYPE; 
             
            pragma interface(c, icd_popen, 11265); 
         
         
            /* ------------ PROCEDURE ICD_PCLOSE ----------- */ 
            /* 
            ** Function ICD_PCLOSE -- Interface routine to C function pclose 
            ** 
            ** This function acts as the interface to the pclose function in 
            ** libc. 
            */ 
            PROCEDURE icd_pclose(funcHandle in ora_ffi.funcHandleType, 
                                 stream in out ORA_FFI.POINTERTYPE); 
             
            pragma interface(c, icd_pclose, 11265); 
         
             
            /* ------------ FUNCTION ICD_FGETS ----------- */ 
            /* 
            ** Function ICD_FGETS -- Interface routine to C function fgets 
            ** 
            ** This function acts as the interface to the fgets function in 
            ** libc. 
            */ 
            FUNCTION icd_fgets(funcHandle in ora_ffi.funcHandleType, 
                               s in out VARCHAR2, n in PLS_INTEGER, 
                               stream in out ORA_FFI.POINTERTYPE) 
            RETURN ORA_FFI.POINTERTYPE; 
         
            pragma interface(c, icd_fgets, 11265); 
         
             
            /* ------------ FUNCTION ICD_FPUTS ----------- */ 
            /* 
            ** Function ICD_FPUTS -- Interface routine to C function fputs 
            ** 
            ** This function acts as the interface to the fputs function in 
            ** libc. 
            */ 
            PROCEDURE icd_fputs(funcHandle in ora_ffi.funcHandleType, 
                                s in out VARCHAR2, 
                                stream in out ORA_FFI.POINTERTYPE); 
         
            pragma interface(c, icd_fputs, 11265); 
         
             
            /* ------------ FUNCTION POPEN ----------- */ 
            /* 
            ** Function POPEN -- Open a Un*x pipe command 
            */ 
            FUNCTION popen(command in VARCHAR2, 
                           ctype in VARCHAR2) 
            RETURN PIPE is 
         
                /* 
                ** Take a copy of the arguments because we need to pass them 
                ** IN OUT to icd_popen, but we really don't want people to have 
                ** to call our routines in the same way. 
                */ 
                cmd varchar2(1024) := command; 
                cmode varchar2(1) := ctype; 
         
                stream PIPE; 
            BEGIN 
                if (cmode not in (READ_MODE, WRITE_MODE)) 
                   or (cmode is NULL) 
                   or (cmd is NULL) 
                then 
                    raise VALUE_ERROR; 
                end if; 
         
                stream.file_handle := icd_popen(fh_popen, cmd, cmode); 
                stream.is_open := TRUE; 
                stream.read_write_mode := ctype; 
                return(stream); 
            END popen; 
             
         
            /* ------------ PROCEDURE PCLOSE ----------- */ 
            /* 
            ** Procedure PCLOSE -- Close a pipe 
            */ 
            PROCEDURE pclose(stream in out PIPE) is 
            BEGIN 
                icd_pclose(fh_pclose, stream.file_handle); 
                stream.is_open := FALSE; 
            END pclose; 
             
         
            /* ------------ FUNCTION GET_LINE ----------- */ 
            /* 
            ** Function GET_LINE -- Get a line of text into a buffer 
            ** from the read mode pipe. 
            */ 
            FUNCTION get_line(stream in out PIPE, 
                              s in out VARCHAR2, n in PLS_INTEGER) 
            RETURN BOOLEAN is 
                buffer ORA_FFI.POINTERTYPE; 
            BEGIN 
                if (n <= 0)  
                   or (stream.is_open = FALSE) 
                   or (stream.is_open is NULL) 
                   or (stream.read_write_mode <> READ_MODE) 
                then 
                    raise VALUE_ERROR; 
                end if; 
         
                /* 
                ** Initialise the Buffer area to reserve the correct amount of space. 
                */ 
         
                s := rpad(' ', n); 
         
                buffer := icd_fgets(fh_fgets, s, n, stream.file_handle); 
         
                /* 
                ** Determine whether a NULL pointer was returned. 
                */ 
                return (ora_ffi.is_null_ptr(buffer) = FALSE); 
            END get_line; 
         
         
            /* ------------ PROCEDURE PUT_LINE ----------- */ 
            /* 
            ** Procedure PUT_LINE -- Put a line of text into a a write mode pipe. 
            */ 
            PROCEDURE put_line(stream in out PIPE, 
                               s in VARCHAR2) is 
                buffer varchar2(2048) := s; 
            BEGIN 
                if (stream.is_open = FALSE) 
                   or (stream.is_open is NULL) 
                   or (stream.read_write_mode <> WRITE_MODE) 
                then 
                    raise VALUE_ERROR; 
                end if; 
         
                icd_fputs(fh_fputs, buffer, stream.file_handle); 
                buffer := chr(10); 
                icd_fputs(fh_fputs, buffer, stream.file_handle); 
            END put_line; 
         
         
            /* ------------ FUNCTION IS_OPEN ----------- */ 
            /* 
            ** Function IS_OPEN -- Determines whether a pipe is open. 
            */ 
            FUNCTION is_open(stream in PIPE) 
            RETURN BOOLEAN is 
            BEGIN 
                return(stream.is_open); 
            END is_open; 
         
        BEGIN 
            /* 
            ** Declare a library handle as libc.  (Internal so NULL,NULL) 
            */ 
            lh_libc := ora_ffi.load_library(NULL, NULL); 
            if ora_ffi.is_null_ptr(lh_libc) then 
                raise VALUE_ERROR; 
            end if; 
         
            /* 
            ** Register the popen function, it's return type and arguments. 
            */ 
            fh_popen := ora_ffi.register_function(lh_libc, 'popen'); 
            if ora_ffi.is_null_ptr(fh_popen) then 
                raise VALUE_ERROR; 
            end if; 
            ora_ffi.register_return(fh_popen, ORA_FFI.C_DVOID_PTR); 
            ora_ffi.register_parameter(fh_popen, ORA_FFI.C_CHAR_PTR); 
            ora_ffi.register_parameter(fh_popen, ORA_FFI.C_CHAR_PTR); 
         
            /* 
            ** Register the pclose function, it's return type and arguments. 
            */ 
            fh_pclose := ora_ffi.register_function(lh_libc, 'pclose'); 
            if ora_ffi.is_null_ptr(fh_pclose) then 
                raise VALUE_ERROR; 
            end if; 
            ora_ffi.register_return(fh_pclose, ORA_FFI.C_VOID); 
            ora_ffi.register_parameter(fh_pclose, ORA_FFI.C_DVOID_PTR); 
         
            /* 
            ** Register the fgets function, it's return type and arguments. 
            */ 
            fh_fgets := ora_ffi.register_function(lh_libc, 'fgets'); 
            if ora_ffi.is_null_ptr(fh_fgets) then 
                raise VALUE_ERROR; 
            end if; 
            ora_ffi.register_return(fh_fgets, ORA_FFI.C_DVOID_PTR); 
            ora_ffi.register_parameter(fh_fgets, ORA_FFI.C_CHAR_PTR); 
            ora_ffi.register_parameter(fh_fgets, ORA_FFI.C_INT); 
            ora_ffi.register_parameter(fh_fgets, ORA_FFI.C_DVOID_PTR); 
         
            /* 
            ** Register the fputs function, it's return type and arguments. 
            */ 
            fh_fputs := ora_ffi.register_function(lh_libc, 'fputs'); 
            if ora_ffi.is_null_ptr(fh_fputs) then 
                raise VALUE_ERROR; 
            end if; 
            ora_ffi.register_return(fh_fputs, ORA_FFI.C_VOID); 
            ora_ffi.register_parameter(fh_fputs, ORA_FFI.C_CHAR_PTR); 
            ora_ffi.register_parameter(fh_fputs, ORA_FFI.C_DVOID_PTR); 
         
        END ora_pipe_io; 
        

        6.3 Form Builderアプリケーションの作成と修正を行うためのオープンAPIの使用

        この項では、Form Builderアプリケーションを作成および変更するための非インタラクティブなプログラミング方法を説明します。この項では次の項目について説明します。

        6.3.1 オープンAPI

        オープンAPIは、非インタラクティブな環境においてフォーム・モジュールの作成または変更を行うための機能と柔軟性を求めるC/C++開発者のためのForm Builder拡張機能です。

        注意: オープンAPIを使用する前に、Form Builderオブジェクトおよびそのプロパティとリレーションについて完全に理解してください。

        6.3.1.1 オープンAPIを利用する場合

        開発の変更内容を多数のフォーム・モジュールにすばやく反映させたい場合は、オープンAPIを使用します。たとえば、オープンAPIを使用して、アプリケーションのルック&フィールを現行の企業規格に更新します。この場合、フォーム・モジュールの更新は数百にのぼることもあります。

        オープンAPIには他にも次のような使用方法があります。

        • 一連のフォームをコンパイルします。

        • 依存性情報を収集します。

        • 独自のドキュメントを書き込みます。

        6.3.1.2 オープンAPIヘッダー・ファイル

        オープンAPIは、1つのForm Builderオブジェクトに対して1つのCヘッダー・ファイルから構成されています。Form Builderオブジェクトは34個あります(図を参照)。これらのオブジェクトは、設計時に使い慣れているForm Builderオブジェクトと対応しています。各ヘッダー・ファイルには、Form Builderオブジェクトの作成および操作に使用する関数やマクロが複数含まれています。

        6.3.1.3 オープンAPIプロパティ

        オープンAPIでは、オブジェクト・プロパティを設定してForm Builderオブジェクトを操作します。

        オープンAPIプロパティには、D2FP_FONT_NAMをはじめとする一意の名前があります。これらのプロパティは、設計時に使い慣れているForm Builderプロパティと対応しています。

        プロパティには次のものがあります。Boolean、Text、Number、Object、またはBlobです。

        次の表では、共通項目プロパティおよびそれらと対応するオープンAPI等価プロパティをリストします。

        オープンAPIプロパティ  Form Builder(設計時)プロパティ 

        D2FP_ACCESS_KEY 

        アクセス・キー 

        D2FP_BEVEL_STY 

        凹凸 

        D2FP_CNV_NAM 

        キャンバス 

        D2FP_ENABLED 

        変更可 

        D2FP_FONT_NAM 

        フォント名 

        D2FP_HEIGHT 

        幅/高さ 

        D2FP_X_POS 

        X位置 

        D2FP_Y_POS 

        Y位置 

        6.3.1.4 オープンAPIファンクションとマクロ

        オープンAPIファンクションおよびマクロを使用して、オブジェクト・プロパティの作成、破棄、複製、サブクラス化、取得、設定を行うことができます。

        たとえば、項目のフォント・サイズを決めるには、D2FITMG_FONT_SIZマクロを使用します。

           d2fitmg_font_siz(ctx, obj, val);
        

        このマクロは、項目オブジェクトのフォント・サイズ・プロパティの値をタイプ番号として戻します。

        テキスト項目プロパティを設定するには、D2FITMST_SETTEXTPROPファンクションを使用します。

           d2fitmst_SetTextProp(d2fctx *pd2fctx, d2fitm *pd2fitm, ub2 pnum,text *prp );
        

        このファンクションは、指定の項目テキスト・プロパティの値を設定します。ポインタをpd2fctxの内容に、項目をpd2fitmに、プロパティ番号をpnumに、ハンドルをprpのテキスト値に指定します。

        6.3.2 オープンAPI使用のガイドライン

        項目  推奨事項 

        ファイル・バックアップ 

        オープンAPIは非インタラクティブです。妥当性チェックおよびエラー・チェックはサポートされていません。オープンAPIを使用する前に、フォーム・モジュール(.FMB)をバックアップしてください。 

        リレーション・オブジェクトの作成 

        リレーション・オブジェクトの作成時に、次のことを行う必要があります。

        • オブジェクトを作成します。

        • リレーション・オブジェクト・プロパティを設定します。

        • d2frelup_Updateファンクションをコールして、オブジェクトのインスタンスを生成します。

         
        オープンAPIを動作させるとき、これらのガイドラインを考慮してください。

        6.3.3 オープンAPIの使用

        この項では、オープンAPIを使用してForm Builderモジュールを作成および変更するための詳細な手順を説明します。

        6.3.3.1 オープンAPIを使用したモジュールの作成と変更

        Form Builderモジュールを作成または変更するには、次のようにします。

        1. 適切なCヘッダー・ファイルをCソース・コードに挿入します。

        2. Cソース・コードにある任意のAPIをコールします。

          • コンテキスト構造を初期化します。

          • ロード・ファンクション・コールを行って、既存のフォーム・モジュール、メニュー・モジュール、またはオブジェクト・ライブラリをオープンします。

          • 所定のオープン・フォームAPIファンクション・コールを行って、既存のデータベースへの接続をはじめとする任意の操作を、必要に応じて行います。

          • 適切なCompileFile()ファンクションを使用して、.FMXまたは.MMXコンパイル・フォームを生成します。

          • 必須のファンクション・コールを行って、対応モジュール(たとえば、フォーム・モジュールのd2ffmdsv_Save()、メニュー・モジュールのd2fmmdsv_Save()、またはオブジェクト・ライブラリのd2folbsv_Save()など)を保存します。

          • 最後に、コンテキスト破棄ファンクションd2fctxde_Destroy()をコールして、オープン・フォームAPIコンテキストを破棄します。このファンクションのコールは最後に行う必要があることに注意してください。

        3. ソース・ファイルをオープンAPIライブラリ(ifd2f60.lib)にリンクします。

        4. ファイルをコンパイルして実行プログラム(.EXEファイル)を作成します。

        5. 実行プログラムを実行してフォーム・モジュール(.FMB)の作成または変更を行います。

        6.3.4 オープンAPIの例

        この項では、複数の例を示しながらオープンAPIの使用方法を説明します。

        6.3.4.1 オープンAPIを使用したモジュールの変更

        /* 
        This example determines if the Form Builder object is a subclassed object and 
        returns the file path of the parent to NULL if the object is subclassed. This sample 
        only processes the following object types:  form level triggers, alerts, blocks, 
        items, item level triggers, radio buttons, and block level triggers.  Use a similar 
        method to process other object types. 
        */
        #include <stdio.h>
        #include <string.h>
        #include <windows.h>
        #include <d2ferr.h>
        #include <d2fctx.h>
        #include <d2ffmd.h>
        #include <d2fblk.h>
        #include <d2fitm.h>
        #include <d2falt.h>
        #include <d2ftrg.h>
        #include <d2frdb.h>
        #define BUFSIZE 128
        int WINAPI WinMain(HANDLE hInstance,
                           HANDLE hPrevInstance,
                           LPSTR lpszCommandLine,
                           int cmdShow)
        {
            d2fctx*   pd2fctx;
            d2ffmd*   pd2ffmd;
            d2fblk*   pd2fblk;
            d2fitm*   pd2fitm;
            d2fctxa   d2fctx_attr;
            d2fstatus status;
            d2falt*   pd2falt;
            d2ftrg*   pd2ftrg;
            d2frdb*   pd2frdb;
            int counter;
            char buf[BUFSIZE];
            char* form_name=(char*)0;
            /* Get the form name from the command line */ 
            strncpy(buf, lpszCommandLine, BUFSIZE);  
            form_name = strtok(buf, ".");
            /* Initialize the attribute mask */
            d2fctx_attr.mask_d2fctxa = 0;
            /* for MS Windows-only attributes */
            d2fctx_attr.d2fihnd_d2fctxa = hInstance;
            d2fctx_attr.d2fphnd_d2fctxa = hPrevInstance;
            d2fctx_attr.d2fcmsh_d2fctxa = cmdShow;
            /* Create the API context */
            status = d2fctxcr_Create(&pd2fctx, &d2fctx_attr);
            /* Load the form */     
            status = d2ffmdld_Load(pd2fctx, &pd2ffmd, form_name, FALSE) ;   
            if (status == D2FS_D2FS_SUCCESS)
            {
              /*** Process Form Level Trigger Objects ***/
              for(status = d2ffmdg_trigger(pd2fctx,pd2ffmd,&pd2ftrg);
                  pd2ftrg != NULL;
                  status = d2ftrgg_next(pd2fctx,pd2ftrg,&pd2ftrg))
              {    
                if (d2ftrgis_IsSubclassed(pd2fctx,pd2ftrg) == D2FS_YES)  
                    d2ftrgs_par_flpath(pd2fctx,pd2ftrg,NULL);
              }
              /*** Process Alert Objects ***/
              for(status = d2ffmdg_alert(pd2fctx,pd2ffmd,&pd2falt);
                  pd2falt != NULL;
                  status = d2faltg_next(pd2fctx,pd2falt,&pd2falt)) 
              {
                if (d2faltis_IsSubclassed(pd2fctx,pd2falt) == D2FS_YES)
                    d2falts_par_flpath(pd2fctx,pd2falt,NULL); 
              }
              /*** Process Block Objects ***/
              for(status = d2ffmdg_block(pd2fctx,pd2ffmd,&pd2fblk);
                  pd2fblk != NULL;
                  status = d2fblkg_next(pd2fctx,pd2fblk,&pd2fblk)) 
              {     
                if (d2fblkis_IsSubclassed(pd2fctx,pd2fblk) == D2FS_YES)
                   d2fblks_par_flpath(pd2fctx,pd2fblk,NULL);
              }
              /* Process Item Objects */
              for(status = d2fblkg_item(pd2fctx,pd2fblk,&pd2fitm);
                  pd2fitm != NULL;
                  status = d2fitmg_next(pd2fctx,pd2fitm,&pd2fitm)) 
              {
                if (d2fitmis_IsSubclassed(pd2fctx,pd2fitm) == D2FS_YES)
                   d2fitms_par_flpath(pd2fctx,pd2fitm,NULL); 
                /* Process Item Level Trigger Objects */
                 for(status = d2fitmg_trigger(pd2fctx,pd2fitm,&pd2ftrg);
                     pd2ftrg != NULL;
                     status = d2ftrgg_next(pd2fctx,pd2ftrg,&pd2ftrg)) 
                 {  
                     if (d2ftrgis_IsSubclassed(pd2fctx,pd2ftrg)==D2FS_YES)
                     {
                       d2ftrgs_par_flpath(pd2fctx,pd2ftrg,NULL);
                       printf("item trigger is Subclassed\n");
                     }
                     else if  (d2ftrgis_IsSubclassed(pd2fctx,
                                                    pd2ftrg)==D2FS_NO)
                     printf("item trigger is NOT Subclassed\n");
                 }
              /* Process Radio Button Objects *
                for(status = d2fitmg_rad_but(pd2fctx,pd2fitm,&pd2frdb);
                    pd2frdb != NULL;
                    status = d2frdbs_next(pd2fctx,pd2frdb,&pd2frdb)) 
                {   
                    if (d2frdbis_IsSubclassed(pd2fctx,pd2frdb)==D2FS_YES
                    {
                      d2frdbs_par_flpath(pd2fctx,pd2frdb,NULL); 
                      printf("radio button is Subclassed\n");
                    }
                    else if (d2frdbis_IsSubclassed(pd2fctx,
                                                 pd2frdb)==D2FS_NO)
                    printf("radio button is NOT Subclassed\n");
               }
              } 
              /* Process Block Level Trigger Objects */  
              for(status = d2fblkg_trigger(pd2fctx,pd2fblk,&pd2ftrg);
                  pd2ftrg != NULL;
                  status = d2ftrgg_next(pd2fctx,pd2ftrg,&pd2ftrg)) 
              {
                  if (d2ftrgis_IsSubclassed(pd2fctx,pd2ftrg) == D2FS_YES)
                  {
                    d2ftrgs_par_flpath(pd2fctx,pd2ftrg,NULL); 
                    printf("block trigger is Subclassed\n"); 
                  }
                  else if (d2ftrgis_IsSubclassed(pd2fctx,
                                                  pd2ftrg)==D2FS_NO)
                  printf("block trigger is NOT Subclassed\n");
              }
            
             /* Save out the form */
             d2ffmdsv_Save(pd2fctx, pd2ffmd, (text *)0, FALSE) ;   
             /* Generate the forms executable (fmx) */
             d2ffmdcf_CompileFile(pd2fctx, pd2ffmd ) ;   
             /* Destroy the API Context */
             d2fctxde_Destroy(pd2fctx) ; 
            }
        }
        

        6.3.4.2 オープンAPIを使用したモジュールの作成

        /* 
        This example creates a master-detail form based on the dept and emp database tables 
        owned by the user scott.  The master contains the following fields: empno, ename, 
        job, sal, and deptno.  The detail contains the following fields deptno, dname, and 
        loc.  The join condition is deptno.  
        */
        #include<stdio.h>
        #include<string.h>
        #include<windows.h>
        #include<d2fctx.h>
        #include<d2ffmd.h>
        #include<d2ffpr.h>
        #include<d2fob.h>
        #include<d2fcnv.h>
        #include<d2ftrg.h>
        #include<d2blk.h>
        #include<d2fitm.h>
        #include<d2fwin.h>
        #include<d2frel.h>
        #define D2FS_SUCCESS 0
        #define FAIL 1
        #define BUFSIZE 128
        #define WBP_TXT "null;\n"
        int WINAPI WinMain(HANDLE hInstance,
                           HANDLE hPrevInstance,
                           LPSTR lpszCommandLine,
                           int cmdShow)
        {
        d2fctx  *pd2fctx;
        d2ffmd  *pd2ffmd;
        d2fcnv  *pd2fcnv;
        d2fwin  *pd2fwin;
        d2fblk  *pempblk;
        d2fblk  *pdeptblk;
        d2frel  *pd2frel;
        d2fitm  *pEempnoitm;
        d2fitm  *pEenameitm;
        d2fitm  *pEjobitm;
        d2fitm  *pEsalitm;
        d2fitm  *pEdeptnoitm;
        d2fitm  *pDdeptnoitm;
        d2fitm  *pDdnameitm;
        d2fitm  *pDlocitm;
        text  *name = (text *)0;
        text  *form_name = (text *)0;
        d2fctxa  d2fctx_attr;
        d2fstatus retval;
        char buf[BUFSIZE];
        /* Get form name */ 
        strncpy(buf, "empdept", BUFSIZE);  
        form_name = (text*)strtok(buf, ".");
        /* Initialize the attribute mask */
        d2fctx_attr.mask_d2fctxa = 0;
        /* for MS Windows-only attributes */
        d2fctx_attr.d2fihnd_d2fctxa = hInstance;
        d2fctx_attr.d2fphnd_d2fctxa = hPrevInstance;
        d2fctx_attr.d2fcmsh_d2fctxa = cmdShow;
        /* Create the API context */
        status = d2fctxcr_Create(&pd2fctx, &d2fctx_attr);
        /* Create the context */
        d2fctxcn_Connect(pd2fctx, (text*)"scott/tiger@test");
        /* Create the form */
        d2ffmdcr_Create(pd2fctx, &pd2ffmd, form_name);
        /* Create a window */
        d2fwincr_Create(pd2fctx,pd2ffmd,&pd2fwin,(text*)"MYWIN");
        /*** Create Canvas and set canvas-related properties ***/
        /* Create a canvas */
        d2fcnvcr_Create(pd2fctx, pd2ffmd, &pd2fcnv, (text*)"MYCANVAS");
        /* Set viewport width */
        d2fcnvs_vprt_wid(pd2fctx, pd2fcnv, 512);
        /* Set viewport height */
        d2fcnvs_vprt_hgt(pd2fctx, pd2fcnv, 403);
        /* Set window */
        dwfcnvs_wnd_obj(pd2fctx, pd2fcnv, pd2fwin);
        /* Set viewport X-position */
        d2fcnvs_vprt_x_pos(pd2fctx, pd2fcnv, 0);
        /* Set viewport Y-position */
        d2fcnvs_vprt_y_pos(pd2fctx, pd2fcnv, 0);
        /* Set width */
        d2fcnvs_width(pd2fctx, pd2fcnv, 538)
        /* Set height */
        d2fcnvs_height(pd2fctx, pd2fcnv, 403)
        /*** Create Emp block and set block-related properties ***/
        /* Create block */
        d2fblkcr_Create(pd2fctx, pd2ffmd, &pempblk, (text*)"EMP");
        /* Set to database block */
        d2fblks_db_blk(pd2fctx, pempblk, TRUE);
        /* Set query data source to Table */
        d2fblks_qry_dat_src_typ(pd2fctx, pempblk, D2FC_QRDA_TABLE);
        /* Set query data source name to EMP table */
        d2fblks_qry_dat_src_nam(pd2fctx, pempblk, "EMP");
        /* Set DML data source type to Table */
        d2fblks_dml_dat_typ(Pd2fctx, pempblk, D2FC_DMDA_TABLE);
        /* Set DML data source name to EMP table */
        d2fblks_dml_dat_nam(pd2fctx, pempblk, (text*)"EMP");
        /*** Create Dept block and set block-related properties ***/
        /* Create block */
        d2fblkcr_Create(pd2fctx, pd2ffmd, &pdeptblk, (text*)"DEPT");
        /* Set to database block */
        d2fblks_db_blk(pd2fctx, pdeptblk, TRUE);
        /* Set query data source to Table */
        d2fblks_qry_dat_src_typ(pd2fctx, pdeptblk, D2FC_QRDA_TABLE);
        /* Set query data source name to EMP table */
        d2fblks_qry_dat_src_nam(pd2fctx, pdeptblk, "DEPT");
        /* Set DML data source type to Table */
        d2fblks_dml_dat_typ(Pd2fctx, pdeptblk, D2FC_DMDA_TABLE);
        /* Set DML data source name to EMP table */
        d2fblks_dml_dat_nam(pd2fctx, pdeptblk, (text*)"DEPT");
        /*** Create empno item and item-related properties ***/
        /* Create item */
        d2fitmcr_Create(pd2fctx, pempblk, &pEempnoitm, (text*)"EMPNO");
        /* Set item type */
        d2fitms_itm_type(pd2fctx, pEempnoitm, D2FC_ITTY_TI);
        /* Set Enable property */
        d2fitms_enabled(pd2fctx, pEempnoitm, TRUE);
        /* Set item (keyboard) navigable property */
        d2fitms_kbrd_navigable(pd2fctx, pEempnoitm, TRUE);
        /* Set item Data Type property */
        d2fitms_dat_typ(pd2fctx, pEempnoitm, D2FC_DATY_NUMBER);
        /* Set item Max Length property */
        d2fitms_max_len(pd2fctx, pEempnoitm, 6);
        /* Set item Required property */
        d2fitms_required(pd2fctx, pEempnoitm, TRUE);
        /* Set Distance Between Records property */
        d2fitms_dist_btwn_recs(pd2fctx, pEempnoitm, 0);
        /* Set Database block(Database Item) property */
        d2fitms_db_itm(pd2fctx, pEempnoitm, TRUE);
        /* Set Query Allowed */
        d2fitms_qry_allowed(pd2fctx, pEempnoitm, TRUE);
        /* Set Query Length */
        d2fitms_qry_len(pd2fctx, pEempnoitm, 6);
        /* Set Update Allowed */
        d2fitms_updt_allowed(pd2fctx, pEempnoitm, TRUE);
        /* Set Item Displayed (Visible) */
        d2fitms_visible(pd2fctx, pEempnoitm, TRUE);
        /* Set Item Canvas property */
        d2fitms_cnv_obj(pd2fctx, pEempnoitm, pd2fcnv);
        /* Set Item X-position */
        d2fitms_x_pos(pd2fctx, pEempnoitm, 32);
        /* Set Item Y-position */
        d2fitms_y_pos(pd2fctx, pEempnoitm, 50);
        /* Set Item Width */
        d2fitms_width(pd2fctx, pEempnoitm, 51);
        /* Set Item Height */
        d2fitms_height(pd2fctx, pEempnoitm, 17);
        /* Set Item Bevel */
        d2fitms_bevel(pd2fctx, pEempnoitm, D2FC_BEST_LOWERED);
        /* Set item Hint */
        d2fitms_hint(pd2fctx, PEempnoitm, (text*)"Enter value for :EMPNO");
        /*** Create Ename item and item-related properties ***/
        /* Create item */
        d2fitmcr_Create(pd2fctx, pempblk, &pEenameitm, (text*)"ENAME");
        /* Set item type */
        d2fitms_itm_type(pd2fctx, pEenameitm, D2FC_ITTY_TI);
        /* Set Enable property */
        d2fitms_enabled(pd2fctx, pEenameitm, TRUE);
        /* Set item (keyboard) navigable property */
        d2fitms_kbrd_navigable(pd2fctx, pEenameitm, TRUE);
        /* Set item Data Type property */
        d2fitms_dat_typ(pd2fctx, pEenameitm, D2FC_DATY_CHAR);
        /* Set item Max Length property */
        d2fitms_max_len(pd2fctx, pEenameitm, 10);
        /* Set Distance Between Records property */
        d2fitms_dist_btwn_recs(pd2fctx, pEenameitm, 0);
        /* Set Database block(Database Item) property */
        d2fitms_db_itm(pd2fctx, pEenameitm, TRUE);
        /* Set Query Allowed */
        d2fitms_qry_allowed(pd2fctx, pEenameitm, TRUE);
        /* Set Query Length */
        d2fitms_qry_len(pd2fctx, pEenameitm, 10);
        /* Set Update Allowed */
        d2fitms_updt_allowed(pd2fctx, pEenameitm, TRUE);
        /* Set Item Displayed (Visible) */
        d2fitms_visible(pd2fctx, pEenameitm, TRUE);
        /* Set Item Canvas property */
        d2fitms_cnv_obj(pd2fctx, pEenameitm, pd2fcnv);
        /* Set Item X-position */
        d2fitms_x_pos(pd2fctx, pEenameitm, 83);
        /* Set Item Y-position */
        d2fitms_y_pos(pd2fctx, pEenameitm, 50);
        /* Set Item Width */
        d2fitms_width(pd2fctx, pEenameitm, 77);
        /* Set Item Height */
        d2fitms_height(pd2fctx, pEenameitm, 17);
        /* Set Item Bevel */
        d2fitms_bevel(pd2fctx, pEenameitm, D2FC_BEST_LOWERED);
        /* Set item Hint */
        d2fitms_hint(pd2fctx, PEenameitm, (text*)"Enter value for :ENAME");
        /*** Create JOB item and item-related properties ***/
        /* Create item */
        d2fitmcr_Create(pd2fctx, pempblk, &pEjobitm, (text*)"JOB");
        /* Set item type */
        d2fitms_itm_type(pd2fctx, pEjobitm, D2FC_ITTY_TI);
        /* Set Enable property */
        d2fitms_enabled(pd2fctx, pEjobitm, TRUE);
        /* Set item (keyboard) navigable property */
        d2fitms_kbrd_navigable(pd2fctx, pEjobitm, TRUE);
        /* Set item Data Type property */
        d2fitms_dat_typ(pd2fctx, pEjobitm, D2FC_DATY_CHAR);
        /* Set item Max Length property */
        d2fitms_max_len(pd2fctx, pEjobitm, 9);
        /* Set Distance Between Records property */
        d2fitms_dist_btwn_recs(pd2fctx, pEjobitm, 0);
        /* Set Database block(Database Item) property */
        d2fitms_db_itm(pd2fctx, pEjobitm, TRUE);
        /* Set Query Allowed */
        d2fitms_qry_allowed(pd2fctx, pEjobitm, TRUE);
        /* Set Query Length */
        d2fitms_qry_len(pd2fctx, pEjobitm, 9);
        /* Set Update Allowed */
        d2fitms_updt_allowed(pd2fctx, pEjobitm, TRUE);
        /* Set Item Displayed (Visible) */
        d2fitms_visible(pd2fctx, pEjobitm, TRUE);
        /* Set Item Canvas property */
        d2fitms_cnv_obj(pd2fctx, pEjobitm, pd2fcnv);
        /* Set Item X-position */
        d2fitms_x_pos(pd2fctx, pEjobitm, 160);
        /* Set Item Y-position */
        d2fitms_y_pos(pd2fctx, pEjobitm, 50);
        /* Set Item Width */
        d2fitms_width(pd2fctx, pEjobitm, 70);
        /* Set Item Height */
        d2fitms_height(pd2fctx, pEjobitm, 17);
        /* Set Item Bevel */
        d2fitms_bevel(pd2fctx, pEjobitm, D2FC_BEST_LOWERED);
        /* Set item Hint */
        d2fitms_hint(pd2fctx, PEjobitm, (text*)"Enter value for :JOB");
        /*** Create SALARY item and item-related properties ***/
        /* Create item */
        d2fitmcr_Create(pd2fctx, pempblk, &pEsalitm, (text*)"SAL");
        /* Set item type */
        d2fitms_itm_type(pd2fctx, pEsalitm, D2FC_ITTY_TI);
        /* Set Enable property */
        d2fitms_enabled(pd2fctx, pEsalitm, TRUE);
        /* Set item (keyboard) navigable property */
        d2fitms_kbrd_navigable(pd2fctx, pEsalitm, TRUE);
        /* Set item Data Type property */
        d2fitms_dat_typ(pd2fctx, pEsalitm, D2FC_DATY_NUMBER);
        /* Set item Max Length property */
        d2fitms_max_len(pd2fctx, pEsalitm, 9);
        /* Set Distance Between Records property */
        d2fitms_dist_btwn_recs(pd2fctx, pEsalitm, 0);
        /* Set Database block(Database Item) property */
        d2fitms_db_itm(pd2fctx, pEsalitm, TRUE);
        /* Set Query Allowed */
        d2fitms_qry_allowed(pd2fctx, pEsalitm, TRUE);
        /* Set Query Length */
        d2fitms_qry_len(pd2fctx, pEsalitm, 9);
        /* Set Update Allowed */
        d2fitms_updt_allowed(pd2fctx, pEsalitm, TRUE);
        /* Set Item Displayed (Visible) */
        d2fitms_visible(pd2fctx, pEsalitm, TRUE);
        /* Set Item Canvas property */
        d2fitms_cnv_obj(pd2fctx, pEsalitm, pd2fcnv);
        /* Set Item X-position */
        d2fitms_x_pos(pd2fctx, pEsalitm, 352);
        /* Set Item Y-position */
        d2fitms_y_pos(pd2fctx, pEsalitm, 50);
        /* Set Item Width */
        d2fitms_width(pd2fctx, pEsalitm, 70);
        /* Set Item Height */
        d2fitms_height(pd2fctx, pEsalitm, 17);
        /* Set Item Bevel */
        d2fitms_bevel(pd2fctx, pEsalitm, D2FC_BEST_LOWERED);
        /* Set item Hint */
        d2fitms_hint(pd2fctx, PEsalitm, (text*)"Enter value for :SAL");
        /*** Create DEPTNO item and item-related properties ***/
        /* Create item */
        d2fitmcr_Create(pd2fctx, pempblk, &pEdeptnoitm, (text*)"DEPTNO");
        /* Set item type */
        d2fitms_itm_type(pd2fctx, pEdeptnoitm, D2FC_ITTY_TI);
        /* Set Enable property */
        d2fitms_enabled(pd2fctx, pEdeptnoitm, TRUE);
        /* Set item (keyboard) navigable property */
        d2fitms_kbrd_navigable(pd2fctx, pEdeptnoitm, TRUE);
        /* Set item Data Type property */
        d2fitms_dat_typ(pd2fctx, pEdeptnoitm, D2FC_DATY_NUMBER);
        /* Set item Max Length property */
        d2fitms_max_len(pd2fctx, pEdeptnoitm, 4);
        /*Set item Required property */
        d2fitms_required(pd2fctx, pEdeptnoitm, TRUE);
        /* Set Distance Between Records property */
        d2fitms_dist_btwn_recs(pd2fctx, pEdeptnoitm, 0);
        /* Set Database block(Database Item) property */
        d2fitms_db_itm(pd2fctx, pEdeptnoitm, TRUE);
        /* Set Query Allowed */
        d2fitms_qry_allowed(pd2fctx, pEdeptnoitm, TRUE);
        /* Set Query Length */
        d2fitms_qry_len(pd2fctx, pEdeptnoitm, 4);
        /* Set Update Allowed */
        d2fitms_updt_allowed(pd2fctx, pEdeptnoitm, TRUE);
        /* Set Item Displayed (Visible) */
        d2fitms_visible(pd2fctx, pEdeptnoitm, TRUE);
        /* Set Item Canvas property */
        d2fitms_cnv_obj(pd2fctx, pEdeptnoitm, pd2fcnv);
        /* Set Item X-position */
        d2fitms_x_pos(pd2fctx, pEdeptnoitm, 493);
        /* Set Item Y-position */
        d2fitms_y_pos(pd2fctx, pEdeptnoitm, 50);
        /* Set Item Width */
        d2fitms_width(pd2fctx, pEdeptnoitm, 30);
        /* Set Item Height */
        d2fitms_height(pd2fctx, pEdeptnoitm, 17);
        /* Set Item Bevel */
        d2fitms_bevel(pd2fctx, pEdeptnoitm, D2FC_BEST_LOWERED);
        /* Set item Hint */
        d2fitms_hint(pd2fctx, PEdeptnoitm, (text*)"Enter value for :DEPTNO");
        /*** Create DEPTNO item and item-related properties ***/
        /* Create item */
        d2fitmcr_Create(pd2fctx, pdeptblk, &pDdeptnoitm, (text*)"DEPTNO");
        /* Set item type */
        d2fitms_itm_type(pd2fctx, pDdeptnoitm, D2FC_ITTY_TI);
        /* Set Enable property */
        d2fitms_enabled(pd2fctx, pDdeptnoitm, TRUE);
        /* Set item (keyboard) navigable property */
        d2fitms_kbrd_navigable(pd2fctx, pDdeptnoitm, TRUE);
        /* Set item Data Type property */
        d2fitms_dat_typ(pd2fctx, pDdeptnoitm, D2FC_DATY_NUMBER);
        /* Set item Max Length property */
        d2fitms_max_len(pd2fctx, pDdeptnoitm, 4);
        /*Set item Required property */
        d2fitms_required(pd2fctx, pDdeptnoitm, TRUE);
        /* Set Distance Between Records property */
        d2fitms_dist_btwn_recs(pd2fctx, pDdeptnoitm, 0);
        /* Set Database block(Database Item) property */
        d2fitms_db_itm(pd2fctx, pDdeptnoitm, TRUE);
        /* Set Query Allowed */
        d2fitms_qry_allowed(pd2fctx, pDdeptnoitm, TRUE);
        /* Set Query Length */
        d2fitms_qry_len(pd2fctx, pDdeptnoitm, 4);
        /* Set Update Allowed */
        d2fitms_updt_allowed(pd2fctx, pDdeptnoitm, TRUE);
        /* Set Item Displayed (Visible) */
        d2fitms_visible(pd2fctx, pDdeptnoitm, TRUE);
        /* Set Item Canvas property */
        d2fitms_cnv_obj(pd2fctx, pDdeptnoitm, pd2fcnv);
        /* Set Item X-position */
        d2fitms_x_pos(pd2fctx, pDdeptnoitm, 32);
        /* Set Item Y-position */
        d2fitms_y_pos(pd2fctx, pDdeptnoitm, 151);
        /* Set Item Width */
        d2fitms_width(pd2fctx, pDdeptnoitm, 38);
        /* Set Item Height */
        d2fitms_height(pd2fctx, pDdeptnoitm, 17);
        /* Set Item Bevel */
        d2fitms_bevel(pd2fctx, pDdeptnoitm, D2FC_BEST_LOWERED);
        /* Set item Hint */
        d2fitms_hint(pd2fctx, PDdeptnoitm, (text*)"Enter value for :DEPTNO");
        /*** Create DNAME item and item-related properties ***/
        /* Create item */
        d2fitmcr_Create(pd2fctx, pdeptblk, &pDdnameitm, (text*)"DNAME");
        /* Set item type */
        d2fitms_itm_type(pd2fctx, pDdnameitm, D2FC_ITTY_TI);
        /* Set Enable property */
        d2fitms_enabled(pd2fctx, pDdnameitm, TRUE);
        /* Set item (keyboard) navigable property */
        d2fitms_kbrd_navigable(pd2fctx, pDdnameitm, TRUE);
        /* Set item Data Type property */
        d2fitms_dat_typ(pd2fctx, pDdnameitm, D2FC_DATY_CHAR);
        /* Set item Max Length property */
        d2fitms_max_len(pd2fctx, pDdnameitm, 14);
        /* Set Distance Between Records property */
        d2fitms_dist_btwn_recs(pd2fctx, pDdnameitm, 0);
        /* Set Database block(Database Item) property */
        d2fitms_db_itm(pd2fctx, pDdnameitm, TRUE);
        /* Set Query Allowed */
        d2fitms_qry_allowed(pd2fctx, pDdnameitm, TRUE);
        /* Set Query Length */
        d2fitms_qry_len(pd2fctx, pDdnameitm, 14);
        /* Set Update Allowed */
        d2fitms_updt_allowed(pd2fctx, pDdnameitm, TRUE);
        /* Set Item Displayed (Visible) */
        d2fitms_visible(pd2fctx, pDdnameitm, TRUE);
        /* Set Item Canvas property */
        d2fitms_cnv_obj(pd2fctx, pDdnameitm, pd2fcnv);
        /* Set Item X-position */
        d2fitms_x_pos(pd2fctx, pDdnameitm, 70);
        /* Set Item Y-position */
        d2fitms_y_pos(pd2fctx, pDdnameitm, 151);
        /* Set Item Width */
        d2fitms_width(pd2fctx, pDdnameitm, 102);
        /* Set Item Height */
        d2fitms_height(pd2fctx, pDdnameitm, 17);
        /* Set Item Bevel */
        d2fitms_bevel(pd2fctx, pDdnameitm, D2FC_BEST_LOWERED);
        /* Set item Hint */
        d2fitms_hint(pd2fctx, PDdnameitm, (text*)"Enter value for :DNAME");
        /*** Create LOC item and item-related properties ***/
        /* Create item */
        d2fitmcr_Create(pd2fctx, pdeptblk, &pDlocitm, (text*)"LOC");
        /* Set item type */
        d2fitms_itm_type(pd2fctx, pDlocitm, D2FC_ITTY_TI);
        /* Set Enable property */
        d2fitms_enabled(pd2fctx, pDlocitm, TRUE);
        /* Set item (keyboard) navigable property */
        d2fitms_kbrd_navigable(pd2fctx, pDlocitm, TRUE);
        /* Set item Data Type property */
        d2fitms_dat_typ(pd2fctx, pDlocitm, D2FC_DATY_CHAR);
        /* Set item Max Length property */
        d2fitms_max_len(pd2fctx, pDlocitm, 13);
        /* Set Distance Between Records property */
        d2fitms_dist_btwn_recs(pd2fctx, pDlocitm, 0);
        /* Set Database block(Database Item) property */
        d2fitms_db_itm(pd2fctx, pDlocitm, TRUE);
        /* Set Query Allowed */
        d2fitms_qry_allowed(pd2fctx, pDlocitm, TRUE);
        /* Set Query Length */
        d2fitms_qry_len(pd2fctx, pDlocitm, 13);
        /* Set Update Allowed */
        d2fitms_updt_allowed(pd2fctx, pDlocitm, TRUE);
        /* Set Item Displayed (Visible) */
        d2fitms_visible(pd2fctx, pDlocitm, TRUE);
        /* Set Item Canvas property */
        d2fitms_cnv_obj(pd2fctx, pDlocitm, pd2fcnv);
        /* Set Item X-position */
        d2fitms_x_pos(pd2fctx, pDlocitm, 173);
        /* Set Item Y-position */
        d2fitms_y_pos(pd2fctx, pDlocitm, 151);
        /* Set Item Width */
        d2fitms_width(pd2fctx, pDlocitm, 96);
        /* Set Item Height */
        d2fitms_height(pd2fctx, pDlocitm, 17);
        /* Set Item Bevel */
        d2fitms_bevel(pd2fctx, pDlocitm, D2FC_BEST_LOWERED);
        /* Set item Hint */
        d2fitms_hint(pd2fctx, PDlocitm, (text*)"Enter value for :LOC");
        /*** Create Relations and relations-related properties ***/
        /* Create Relation */
        d2frelcr_Create(pd2fctx, (d2fob *)pdeptblk, &pd2frel, (text*)"DEPT_EMP");
        /* Set Relation Detail block */
        d2frels_detail_blk(pd2fctx, pd2frel, (text *)"EMP");
        /* Set Master Deletes property */
        d2frels_del_rec([pd2fctx, pd2frel, D2FC_DERE_NON_ISOLATED);
        /* Set Deferred property */
        d2frels_deferred(pd2ctx, pd2frel, FALSE);
        /* Set Auto Query property */
        d2frels_auto_qry(pd2ctx, pd2frel, FALSE);
        /* Set Prevent Masterless property */
        d2frels_prvnt_mstrless_ops(pd2ctx, pd2frel, FALSE);
        /* Set Join Condition property */
        d2frels_join_cond(pd2ctx, pd2frel, (text*)"DEPTNO");
        /* Instantiate Relation: creates master-detail triggers */
        d2frelup_Update(pd2fctx, pd2frel);
        /* Save Form */
        d2ffmdsv_Save(pd2fctx, pd2ffmd, (text*)0, FALSE, TRUE);
        /* Compile Form */
        d2ffmdcf_CompileFile(pd2fctx, pd2ffmd);
        /* Destroy Context */
        d2fctxde_Destroy(pd2fctx);
        }
        

        6.4 ODBCデータソースに対して実行するアプリケーションの設計

        企業内のデータは、複数の異種データソースに常駐することがよくあります。たとえば、データの一部がOracleデータベースに保存され、別の一部がInformixデータベースに保存されている場合があります。単一でそのすべてのデータソースにアクセスできるアプリケーションの作成は、難しい作業になりかねません。

        しかし、Forms DeveloperおよびReports Developerのオープン・データソース・サポートを利用すれば、すべてのODBC準拠データソースに対して透過的に実行される汎用アプリケーションを構築することができます。

        この項では、オープン・データソース・サポートについて説明します。この項では次の項目について説明します。

        6.4.1 Oracle Open Client Adapter(OCA)

        ODBCデータソースに接続する場合、Oracle Open Client Adapter (OCA)を使用します。OCAはODBCレベル2に準拠したユーティリティで、Microsoft Windows 95、Windows NT環境のForms DeveloperおよびReports Developerでは、これを使用することによりODBCドライバを介してODBC準拠データソースにアクセスできます。

        OCAは、Forms DeveloperおよびReports Developerに含まれています。OCAをインストールするには、Oracle Installerを使用します。

        6.4.1.1 OCAを利用する場合

        アプリケーションで非Oracleデータソースにアクセスする必要がある場合は、必ずOCAを使ってください。Forms DeveloperおよびReports Developerアプリケーションでは、すべてのODBC準拠データソースに自動的にアクセスできます。ODBCデータソースへの接続の詳細は、オンライン・ヘルプを参照してください。

        6.4.1.2 OCAアーキテクチャ

        Oracle Open Client Adapterの構成は次のとおりです。

        コンポーネント  説明 

        Forms DeveloperまたはReports Developerアプリケーション 

        処理を実行してODBCファンクションをコールし、SQL文を送信して結果を取り出します。 

        Oracle Open Client Adapter 

        Oracleデータベース・コールをODBCコールに変換します。 

        ドライバ・マネージャ 

        アプリケーション用のODBCドライバをロードします。 

        ODBCドライバ 

        ODBCファンクション・コールを処理し、SQL要求を指定のデータソースに送信して、結果をアプリケーションに戻します。 

        データソース 

        ユーザーがアクセスを望むデータ、それに対応付けられたオペレーティング・システム、DBMSおよび(もしあるならば)DBMSへのアクセスに使用されるネットワーク・プラットフォームからなります。 

        6.4.1.3 DBC接続の確立

        ODBCデータソースに接続するには、接続ダイアログ・ボックスに次の接続文字列を入力します。

           	[user[/password]]@ODBC:datasource[:dbname]
        
        

        たとえば、Sybase System 10に接続する場合は、次のように入力します。

           scott/tiger@ODBC:sybase_ds
        

        6.4.1.4 ODBCドライバ

        ODBCデータソースに接続する場合、ODBCドライバを使用してデータソースと通信します。Forms DeveloperおよびReports Developerには、サポートしている各データソースに対応したODBCドライバがすでにバンドルされています。これらのドライバはODBCレベル1準拠ですが、パフォーマンスを向上させるためにレベル2の機能性を一部提供しています。

        6.4.1.5 OPENDB.PLL

        OPENDB.PLLは、OCA付属のPL/SQLファンクション・ライブラリです。アプリケーションでOPENDB.PLLを使用すると、次のことができます。

          • 実行時にフォームおよびデータ・ブロック・プロパティを自動調整してデータソースを整えます。

          • アプリケーションのメイン接続のほかに、その他のデータソースへの補助接続を開きます。

          • 接続での任意のSQL文およびストアド・プロシージャ・コールを実行します。

          • 結果をOracle以外のストアド・プロシージャから取り出します。

          • 任意の接続のDBMSおよびODBCドライバ名およびバージョンを取得します。

        OPENDB.PLLの詳細は、ORACLE_ HOME\TOOLS\DOC20ディレクトリのOCA_INFO.PDFを参照してください。

        6.4.2 オープン・データソースのガイドライン

        項目  推奨事項 

        アプリケーションを最適化して、複数のデータソースのフォームを実行します。 

        システムに固有の機能を利用するために特定のデータソースを指定するのでなければ、複数のデータソースに対して実行するためにアプリケーションを最適化する必要はありません。 

        ODBCデータソースと併用するPL/SQLの作成 

        PL/SQLプログラム単位に埋め込まれているSQL文は、接続対象データソースのOracle SQLおよびSQLダイアレクトの両方に適合する必要があります。Oracleと適合しない文の場合、PL/SQLコンパイル・エラーとなります。同様に、サポートされていない構文を使用する文の場合、実行時にエラーとなります。

        SYSDATEファンクションとUSERファンクションのみが、この制限の例外です。この2つはOracle固有のファンクションです。OCAによってこれらのファンクションが対応するODBCファンクションに変換されるため、これらのファンクションはすべてのデータソースに対応することができます。

        データソース固有でも、Oracle構文と競合するSQL文を発行する場合は、EXEC_SQLパッケージを使用します。 

        複数のデータソースからの表の参照 

        多くのデータソースでは、データベース、所有者および表を指定すれば(たとえば、database.owner.tablenameのように)、他のデータソースにある表にアクセスできます。

        しかし、PL/SQLではこのような3つの要素で表を指定する構文が認識されないため、クライアント側のプログラム単位またはトリガーはコンパイルされません。

        この制限に対処するには、まず3部構成の表名を二重引用符で囲み、後に適切なOPENDBファンクションをコールし、二重引用符を削除します。  

        制限 

        • 非Oracle7データソースを処理する場合は、アプリケーション・モジュール(フォーム、レポート、図表)をファイル・システムに保存する必要があります。非Oracle7データソースは、アプリケーション・モジュールを保存するためのリポジトリとして使用することはできません。

        • 列名のトリガー情報へのアクセスは、オブジェクト・ナビゲータ(データベース・オブジェクト・ノード)からは行えません。

        • ストアド・プロシージャ・テキストを表示できるのは、Oracle ALL_SOURCE表をエミュレートするデータソースのみに限られます。データベース・ストアド・プロシージャ・テキストは編集できません。

        • PL/SQLプログラム単位をクライアントから非Oracle7データソースにドラッグ・アンド・ドロップすることはできません。

        • Forms DeveloperおよびReports Developerでは、マスター/ディテール・リレーションのデフォルト選択を行うために主キーおよび外部キーの制約情報を使用することはできません。これらのリレーションは、必要に応じて、直接指定する必要があります。

        • オプティマイザ・ヒント(/*hint*/ の形式のコメント)は、OCAを使用して接続するデータソースでは無視されます。

         

        トラブルシューティング 

        OCA発行のSQL文、およびODBCドライバまたはデータベース生成のメッセージを表示するには、次のようにします。

        1. 次のエントリが、Windows NTおよびWindows 95の場合はレジストリに、Windows3.1の場合はORACLE.INIに設定されていることを確認します。

        UB=ORACLE_HOME\OCA20

      2. エラーが解決できない場合は、サポート担当に連絡してください。

      3. 次のエントリを、Windows NTおよびWindows 95の場合はSOFTWARE\ORACLEのレジストリに、Windows3.1の場合はORACLE.INIに追加します。

        
        

        OCA_DEBUG_SQL=TRUE

        OCA_DEBUG_ERROR=TRUE

      4. ODBCデータソースに対してアプリケーションを実行して、SQL文またはエラー・メッセージをデバッグ・ウィンドウに表示します。デバッグ・ウィンドウをクローズして処理を続行する場合は、「OK」をクリックしてください。

         

      5. デバッグ上のヒント 

        デバッグ情報を表示するには、OCA_DEBUG_SQLおよびOCA_DEBUG_ERROR設定変数をTRUEに設定します。

        これらの環境変数は、OCAデータソースに対してForms DeveloperまたはReports Developerを使用する際のSQLエラーの特定作業に役立ちます。

        OCA_DEBUGTRUEに設定すると、ODBCドライバに送られるSQL文が送信前に表示されます。

        OCA_DEBUG_ERRORTRUEに設定すると、ODBCドライバから戻されたエラーは、Forms DeveloperまたはReports Developerに戻される前にダイアログに表示されます。 

        複数のデータソースを処理する場合は、次のガイドラインを考慮してください。

        6.4.3 ODBCデータソースに対して実行するアプリケーションの設定

        ODBC準拠データソースに対して実行するためにアプリケーションを設定するには、オンライン・ヘルプのトピック「非Oracleデータソースへのアクセス」を参照してください。


戻る 次へ
Oracle
Copyright © 2000 Oracle Corporation.

All Rights Reserved.

目次

索引