Pro*C/C++では、Cプリプロセッサのほとんどのディレクティブがサポートされます。Pro*C/C++プリプロセッサを使用すると、次のような作業を実行できます。
#defineディレクティブを使用した定数およびマクロの定義、VARCHARなどのPro*C/C++のデータ型宣言をパラメータ化する場合の定義済エンティティの使用。
#includeディレクティブを使用した、プリコンパイラに必要なsqlca.hなどのファイルの読取り。
個別のファイルにある定数およびマクロの定義、プリコンパイラでの#includeディレクティブを使用したこのファイルの読取り。
Pro*C/C++プリプロセッサでは、Cプリプロセッサのほとんどのコマンドが認識され、必要なマクロ置換、ファイルのインクルードおよび条件付きのソース・テキストのインクルードまたは除外が効率的に実行されます。Pro*C/C++プリプロセッサでは、この事前処理で取得した値を使用して、ソース出力テキスト(生成される.c出力ファイル)が変更されます。
この点について、次に例を示します。次のプログラムの一部分を記述したとします。
#include "my_header.h" ... VARCHAR name[VC_LEN]; /* a Pro*C-supplied datatype */ char another_name[VC_LEN]; /* a pure C datatype */ ...
カレント・ディレクトリ内のmy_header.hファイルに、特に次の行が含まれているとします。
#define VC_LEN 20
プリコンパイラはファイルmy_header.hを読み込み、VC_LENの定義済の値(20)を使用し、nameの構造体をVARCHAR[20]として宣言します。
charはネイティブな型です。プリコンパイラは、another_name[VC_LEN]の宣言時に20を代入しません。
プリコンパイラはC言語のデータ型の宣言を処理する必要がないため、そのデータ型がホスト変数として指定されてもかまいません。実際にファイルmy_header.hをインクルードして、another_nameの宣言内でVC_LENに20を代入する処理は、Cコンパイラのプリプロセッサの役割です。
Pro*C/C++でサポートされるプリプロセッサ・ディレクティブは、次のとおりです。
#define。プリコンパイラとCまたはC++コンパイラで使用されるマクロを作成します。
#include。プリコンパイラで使用される他のソース・ファイルを読み込みます。
#if。定数式が0に評価される場合にのみ、ソース・テキストをプリコンパイルおよびコンパイルします。
#ifdef。定義済定数の有無に応じてソース・テキストを条件付きでプリコンパイルおよびコンパイルします。
#ifndef。ソース・テキストを条件付きで除外します。
#endif。#if、#ifdefまたは#ifndefコマンドを終了します。
#else。#if、#ifdefまたは#ifndefの条件が満たされない場合に、プリコンパイルおよびコンパイルされるソース・テキストの代替部を選択します。
#elif。定数またはマクロ引数の値に応じて、プリコンパイルおよびコンパイルされるソース・テキストの代替部を選択します。
Pro*C/C++プリプロセッサで使用されないCプリプロセッサ・ディレクティブもあります。これらのディレクティブのほとんどは、プリコンパイラとは無関係です。たとえば、#pragmaはCコンパイラ用のディレクティブであり、プリコンパイラでは処理されません。プリコンパイラで処理されないCプリプロセッサ・ディレクティブは、次のとおりです。
#。プリプロセッサのマクロ・パラメータを文字定数に変換します。
##。2つのプリプロセッサ・トークンを1つのマクロ定義にマージします。
#error。コンパイル時エラー・メッセージを生成します。
#pragma。実装依存情報をCコンパイラに渡します。
#line。Cコンパイラ・メッセージに行番号を提供します。
これらのディレクティブは、Cコンパイラのプリプロセッサでサポートされている場合でも、Pro*C/C++では使用されません。これらのディレクティブのほとんどは、プリコンパイラでは使用されません。コンパイラでサポートされている場合は、これらのディレクティブをPro*C/C++プログラムで使用できますが、CまたはC++コード以外の埋込みSQL文や、プリコンパイラが提供するVARCHARなどのデータ型を使用した変数の宣言では使用できません。
Pro*C/C++では、ORA_PROCというCプリプロセッサのマクロが事前定義されています。このマクロを使用すると、不要または無関係なコード・セクションがプリコンパイラで処理されるのを回避できます。アプリケーションには、プリコンパイル時に必要のない情報を提供する大きなヘッダー・ファイルがインクルードされている場合があります。このようなヘッダー・ファイルは、ORA_PROCマクロに基づいて条件付きで除外すれば、プリコンパイラで読み込まれることはありません。
次の例では、ORA_PROCマクロを使用してirrelevant.hファイルを除外しています。
#ifndef ORA_PROC #include <irrelevant.h> #endif
プリコンパイル時にORA_PROCが定義されているため、irrelevant.hファイルはインクルードされません。
ORA_PROCマクロを使用できる対象は、#ifdefや#ifndefなどのCプリプロセッサ・ディレクティブのみです。EXEC ORACLE条件文では、Cプリプロセッサ・マクロと同じネームスペースは共有されません。したがって、次の例の条件では、事前定義済のORA_PROCマクロを使用しません。
EXEC ORACLE IFNDEF ORA_PROC; <section of code to be ignored> EXEC ORACLE ENDIF;
この場合、この条件コード部分が正常に処理されるように、DEFINEオプションまたはEXEC ORACLE DEFINE文を使用してORA_PROCを設定する必要があります。
各システムのPro*C/C++プリコンパイラでは、sqlca.h、oraca.hおよびsqlda.hなど、プリプロセッサで読み込まれるヘッダー・ファイルが標準的な場所にあるものとみなされます。たとえば、ほとんどのUNIXシステムでの標準的な場所は、$ORACLE_HOME/precomp/publicです。使用しているシステムのデフォルトの場所については、システム固有のOracleマニュアルを参照してください。インクルードする必要のあるヘッダー・ファイルがデフォルトの場所にない場合は、コマンドラインで、EXEC ORACLEオプションとして、INCLUDE=オプションを指定する必要があります。
stdio.hやiostream.hなどのシステム・ヘッダー・ファイルについて、Pro*C/C++にハードコードされているものと異なる格納場所を指定するには、SYS_INCLUDEプリコンパイラ・オプションを使用します。
関連項目:
プリコンパイラ・オプションとEXEC ORACLEオプションについては、プリコンパイラのオプションを参照してください。
#defineコマンドを使用すると、名前付きの定数を作成して、ソース・コード内でマジック番号のかわりに使用できます。VARCHAR[const]など、プリコンパイラで必要な宣言に対して、#defineで指定した定数を使用できます。たとえば、次のコードは不具合を含んでいる可能性があります。
...
VARCHAR emp_name[10];
VARCHAR dept_loc[14];
...
...
/* much later in the code ... */
f42()
{
/* did you remember the correct size? */
VARCHAR new_dept_loc[10];
...
}
次のように記述できます。
#define ENAME_LEN 10
#define LOCATION_LEN 14
VARCHAR new_emp_name[ENAME_LEN];
...
/* much later in the code ... */
f42()
{
VARCHAR new_dept_loc[LOCATION_LEN];
...
}
引数を持つプリプロセッサ・マクロは、Cオブジェクトで使用する場合と同様に、プリコンパイラで処理する必要のあるオブジェクトで使用できます。次に例を示します。
#define ENAME_LEN 10
#define LOCATION_LEN 14
#define MAX(A,B) ((A) > (B) ? (A) : (B))
...
f43()
{
/* need to declare a temporary variable to hold either an
employee name or a department location */
VARCHAR name_loc_temp[MAX(ENAME_LEN, LOCATION_LEN)];
...
}
#include、#ifdefおよび#endifプリプロセッサ・ディレクティブを使用して、プリコンパイラに必要なファイルを条件付きでインクルードできます。次に例を示します。
#ifdef ORACLE_MODE
#include <sqlca.h>
#else
long SQLCODE;
#endif
Pro*C/C++での#defineプリプロセッサ・ディレクティブの使用には、制限があります。#defineディレクティブを使用して、実行SQL文に使用する記号定数を生成することはできません。次の無効な例を参照してください。
#define RESEARCH_DEPT 40
...
EXEC SQL SELECT empno, sal
INTO :emp_number, :salary /* host arrays */
FROM emp
WHERE deptno = RESEARCH_DEPT; /* INVALID! */
#defineしたマクロを有効に使用できる宣言SQL文は、TYPE文とVAR文のみです。したがって、次のマクロ使用例はPro*C/C++で有効です。
#define STR_LEN 40 ... typedef char asciiz[STR_LEN]; ... EXEC SQL TYPE asciiz IS STRING(STR_LEN) REFERENCE; ... EXEC SQL VAR password IS STRING(STR_LEN);
プリプロセッサでは、ディレクティブ#および##が無視され、プリコンパイラで認識する必要のあるトークンが作成されます。これらのコマンドは(コンパイラでサポートされている場合は)、純粋なCコードに使用できます。プリコンパイラでは、これらのコードは処理されません。次の例の場合、プリプロセッサ・コマンド##の使用は無効です。
#define MAKE_COL_NAME(A) col ## A
...
EXEC SQL SELECT MAKE_COL_NAME(1), MAKE_COL_NAME(2)
INTO :x, :y
FROM table1;
プリコンパイラでは##は無視されるため、この例は正しくありません。
Pro*C/C++プリプロセッサで#includeディレクティブが処理される方法については前項で説明しましたが、この方法のために、#includeディレクティブを使用して埋込みSQL文を含むファイルをインクルードできません。#includeは、純粋に宣言文とディレクティブのみを含むファイルをインクルードする場合に使用します。#defineや、プリコンパイラに必要な変数と構造体の宣言のみを含むsqlca.hファイルなどがその例です。
C/C++プリプロセッサの#includeコマンド、あるいはプリコンパイラのEXEC SQL INCLUDEコマンドを使用すると、sqlca.h、oraca.hおよびsqlda.hの各宣言ヘッダー・ファイルをPro*C/C++プログラムにインクルードできます。たとえば、次の文のように、EXEC SQLオプションを指定して、SQL通信領域構造体(SQLCA)をプログラムにインクルードできます。
EXEC SQL INCLUDE sqlca;
C/C++プリプロセッサ・ディレクティブを使用してSQLCAをインクルードするには、次のコードを追加します。
#include <sqlca.h>
関連項目:
sqlca.h、oraca.hおよびsqlda.hヘッダー・ファイルの内容の詳細は、ランタイム・エラーの処理を参照してください。
プリプロセッサの#includeディレクティブを使用する場合は、ファイル拡張子(.hなど)を指定する必要があります。
注意:
#includeディレクティブを使用してSQLCAを複数箇所にインクルードする必要がある場合は、#includeの前にディレクティブ#undef SQLCAを挿入してください。これは、sqlca.hが次の行から開始されるためです。
#ifndef SQLCA
#define SQLCA 1
#includeディレクティブまたはEXEC SQL INCLUDE文を含むファイルをプリコンパイルする場合は、インクルードするすべてのファイルの位置をプリコンパイラに対して指定する必要があります。INCLUDE=オプションは、コマンドライン、システム構成ファイルまたはユーザー構成ファイル内で使用できます。
関連項目:
INCLUDEプリコンパイラ・オプション、インクルード・ファイルの検索手順および構成ファイルの詳細は、プリコンパイラのオプションを参照してください。
sqlca.h、oraca.hおよびsqlda.hなど、標準的なプリプロセッサ・ヘッダー・ファイルのデフォルトの場所は、プリコンパイラ内で事前設定されています。この場所は、システムごとに異なります。使用しているシステムのデフォルトの場所については、システム固有のOracleマニュアルを参照してください。
Pro*C/C++で生成される.c出力ファイルをコンパイルする場合は、コンパイラおよびオペレーティング・システムに用意されているオプションを使用して、インクルード・ファイルの場所を識別する必要があります。
たとえば、ほとんどのUNIXシステムでは、次のコマンドを使用して、生成されるCソース・ファイルをコンパイルできます。
cc -o progname -I$ORACLE_HOME/sqllib/public ... filename.c ...
VAX/OPENVMSシステムでは、事前にインクルード・ディレクトリ・パスを論理VAXC$INCLUDE内の値に設定します。
プログラム内でEXEC SQL INCLUDE文を使用すると、プリコンパイラによりソース・テキストが出力(.c)ファイルにインクルードされます。したがって、EXEC SQL INCLUDEを使用してインクルード・ファイルに、宣言文および埋込みSQLの実行文を入れることができます。
#includeを使用してファイルをインクルードする場合、プリコンパイラでは単にファイルが読み込まれ、#defineで定義したマクロが追跡記録されるのみです。
注意:
VARCHAR宣言とSQL文は、インクルード(#include)ファイルには使用できません。このため、Pro*C/C++プリプロセッサの#includeディレクティブを使用してインクルード・ファイルでは、SQL文を使用できません。
プリコンパイルする必要のあるすべてのインクルード・ファイルの位置は、コマンドラインまたは構成ファイルで指定する必要があります。
たとえば、UNIX環境での開発中に、アプリケーションのインクルード・ファイルがディレクトリ/home/project42/includeにある場合は、このディレクトリをPro*C/C++のコマンドラインとccコマンドラインの両方で指定する必要があります。次のようなコマンドを使用します。
proc iname=my_app.pc include=/home/project42/include ... cc -I/home/project42/include ... my_app.c
または、適切なマクロをMakeファイルに組み込みます。Pro*C/C++アプリケーションのコンパイルとリンクの詳細は、システム固有のOracleマニュアルを参照してください。
関連項目:
プリコンパイラ・オプションと構成ファイルの詳細は、INCLUDEを参照してください。