プライマリ・コンテンツに移動
Pro*C/C++プログラマーズ・ガイド
12c リリース1(12.1)
B71397-03
目次へ移動
目次
索引へ移動
索引

前
次

Cプリプロセッサ

Pro*C/C++では、Cプリプロセッサのほとんどのディレクティブがサポートされます。Pro*C/C++プリプロセッサを使用すると、次のような作業を実行できます。

Pro*C/C++プリプロセッサの機能

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などのデータ型を使用した変数の宣言では使用できません。

ORA_PROCマクロ

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.horaca.hおよびsqlda.hなど、プリプロセッサで読み込まれるヘッダー・ファイルが標準的な場所にあるものとみなされます。たとえば、ほとんどのUNIXシステムでの標準的な場所は、$ORACLE_HOME/precomp/publicです。使用しているシステムのデフォルトの場所については、システム固有のOracleマニュアルを参照してください。インクルードする必要のあるヘッダー・ファイルがデフォルトの場所にない場合は、コマンドラインで、EXEC ORACLEオプションとして、INCLUDE=オプションを指定する必要があります。

stdio.hiostream.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 

#defineの使用について

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; 

プリコンパイラでは##は無視されるため、この例は正しくありません。

#includeに使用できないSQL文

Pro*C/C++プリプロセッサで#includeディレクティブが処理される方法については前項で説明しましたが、この方法のために、#includeディレクティブを使用して埋込みSQL文を含むファイルをインクルードできません。#includeは、純粋に宣言文とディレクティブのみを含むファイルをインクルードする場合に使用します。#defineや、プリコンパイラに必要な変数と構造体の宣言のみを含むsqlca.hファイルなどがその例です。

SQLCA、ORACAおよびSQLDAの組込み

C/C++プリプロセッサの#includeコマンド、あるいはプリコンパイラのEXEC SQL INCLUDEコマンドを使用すると、sqlca.horaca.hおよびsqlda.hの各宣言ヘッダー・ファイルをPro*C/C++プログラムにインクルードできます。たとえば、次の文のように、EXEC SQLオプションを指定して、SQL通信領域構造体(SQLCA)をプログラムにインクルードできます。

EXEC SQL INCLUDE sqlca; 

C/C++プリプロセッサ・ディレクティブを使用してSQLCAをインクルードするには、次のコードを追加します。

#include <sqlca.h> 

関連項目:

sqlca.horaca.hおよびsqlda.hヘッダー・ファイルの内容の詳細は、ランタイム・エラーの処理を参照してください。

プリプロセッサの#includeディレクティブを使用する場合は、ファイル拡張子(.hなど)を指定する必要があります。

注意:

#includeディレクティブを使用してSQLCAを複数箇所にインクルードする必要がある場合は、#includeの前にディレクティブ#undef SQLCAを挿入してください。これは、sqlca.hが次の行から開始されるためです。

      #ifndef SQLCA
      #define SQLCA 1

次に、sqlca.hはSQLCAが定義されていない場合にのみSQLCA構造体を宣言します。

#includeディレクティブまたはEXEC SQL INCLUDE文を含むファイルをプリコンパイルする場合は、インクルードするすべてのファイルの位置をプリコンパイラに対して指定する必要があります。INCLUDE=オプションは、コマンドライン、システム構成ファイルまたはユーザー構成ファイル内で使用できます。

関連項目:

INCLUDEプリコンパイラ・オプション、インクルード・ファイルの検索手順および構成ファイルの詳細は、プリコンパイラのオプションを参照してください。

sqlca.horaca.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および#includeのまとめ

プログラム内でEXEC SQL INCLUDE文を使用すると、プリコンパイラによりソース・テキストが出力(.c)ファイルにインクルードされます。したがって、EXEC SQL INCLUDEを使用してインクルード・ファイルに、宣言文および埋込みSQLの実行文を入れることができます。

#includeを使用してファイルをインクルードする場合、プリコンパイラでは単にファイルが読み込まれ、#defineで定義したマクロが追跡記録されるのみです。

注意:

VARCHAR宣言とSQL文は、インクルード(#include)ファイルには使用できません。このため、Pro*C/C++プリプロセッサの#includeディレクティブを使用してインクルード・ファイルでは、SQL文を使用できません。

定義済マクロ

Cコンパイラのコマンドラインでマクロを定義する場合、アプリケーションの要件によっては、そのマクロをプリコンパイラのコマンドラインでも定義する必要があります。たとえば、UNIXコマンドラインで次のようにコンパイルするとします。

cc -DDEBUG ...

この場合は、次のようにDEFINE=オプションを使用してプリコンパイルする必要があります。

proc DEFINE=DEBUG ...

インクルード・ファイル

プリコンパイルする必要のあるすべてのインクルード・ファイルの位置は、コマンドラインまたは構成ファイルで指定する必要があります。

たとえば、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を参照してください。