15. 複製オブジェクトのデータ定義言語(DDL)
NetZ のデータ定義言語(DDL)を使用すると、 開発者はネットワーク上に送信する必要のあるデータを簡単な少数のステートメントで記述し、ネットワークレイヤーを生成することができます。 そのため、開発者は単一または複数の DDL ファイルを使用して、 NetZ がネットワークレイヤーを管理するデータ構造とゲームオブジェクトを記述します。
単一のゲームに対して、DDL コンパイラには 1 つ以上の DDL ファイルが必要です。 DDL 構文、DDL コンパイラの使用方法、コンパイラで行われるクラス生成についてはこの章で説明しています。 また、用意する必要のある情報についても詳細を説明します。
15.1. DDL ファイル構文
NetZ の DDL はクラスをベースにするオブジェクト指向言語です。 もっとも重要な 3 つのクラスは、DuplicatedObject、DupSpace、DataSet のクラスで、 これらはゲームのすべてのオブジェクトとそれに関するデータセットの基本クラスです。 RMC とアクションは、リモートでメソッドを呼び出す異なる方法です。 すべての DO 、データセット、RMC、アクションが DDL ファイルで宣言されます。 DDL コード内のコメントは、行の先頭にスラッシュを 2 つ付けて示されています。
15.1.1. データ型
NetZ には一般に使用される内蔵データ型数個と、必要に応じて補充できる多数の追加データ型があります。 また、開発者はカスタムデータ型を定義することもできます。 カスタムデータ型を実装すると、他のデータ型と同様に DDL で使用できます。
15.1.1.1. 内蔵データ型
DDL で宣言される変数には、内蔵データ型または有効なユーザー定義のデータ型をどれでも使用できます。 サポートされている内蔵データ型を次の表に示します。 ここに示されているデータ型の array もすべてサポートされています。 cstr の場合、変数は終端 Null 文字まで複製されます。 信頼性のないチャンネルから送信されるデータセットには 3584Byte を超えるデータを含めることはできません。 DDL のデータ型は次の表に従って C++ のデータ型にマッピングされます。
DDL | C++ |
---|---|
bool | qBool |
byte | qByte |
int8 | qInt8 |
int16 | qInt16 |
uint16 | qUnsignedInt16 |
int32 | qInt32 |
uint32 | qUnsignedInt32 |
int64 | qInt64 |
uint64 | qUnsignedInt64 |
float | qFloat |
double | qDouble |
real | qReal |
qchar | qChar |
qchar8 | qChar8 |
qchar16 | qChar16 |
cstr | qChar* |
string | String |
dohandle | DOHandle |
stationurl | StationURL |
datetime | DateTime |
qresult | qResult |
qbuffer | qBuffer |
qlist | qList |
qvector | qVector |
qqueue | qQueue |
memberlist | MemberList |
memberqueue | MemberQueue |
membervector | MemberVector |
15.1.1.2. 用意されている拡張
データ操作のため、NetZ ではプロジェクトのコンパイル時に追加できるデータ型をいくつか用意しています。 中でも次の C++ STL データ型が使用できます。
DDL | C++ |
---|---|
std_ |
qChar |
std_ |
qChar8* |
std_ |
qChar16* |
std_ |
std:: |
std_ |
std:: |
std_ |
std:: |
std_ |
std:: |
std_ |
std:: |
std_ |
std:: |
上の STL データ型をプロジェクトに統合するには、次を使用して STL.ddl ファイルをプロジェクトの DDL ファイルに含める必要があります。
#include <Extensions/STL.ddl>
その後、次の STL ライブラリのどれにリンクするかを指定します。
プロジェクト設定 | STLExt ライブラリ |
---|---|
Unicode デバッグ | STLExtud.lib |
Unicode リリース | STLExtu.lib |
15.1.1.3. カスタムデータ型
開発者はカスタムのデータ型を DDL に定義できます。 このデータ型が DDL に定義されると、内蔵データ型と同様に使用できます。 DDL でカスタムデータ型を定義する際に使用される構文を次に示します。
type TypeName;
TypeName は新しいデータ型の名前です。 新しいデータ型が DDL で宣言されると、開発者は DDLTYPE(TypeName) の名前で C++ クラスを実装し、 この新しいデータ型のマーシャリング(C++ マッピングおよびイン/アウトストリーミングのこと)を実装する必要があります。 このクラスでは、C++ マッピングのデータ型定義は typedef TypeName CPPType の形式にする必要があります。 例えば、DDL データ型として STL 文字列を統合するには次のデータ型を定義できます。
type std_string;
この宣言が MyDDL.ddl ファイルで検出されると、MyDDLTypes.h ファイルには次のように std_strings をマーシャリングするための C++ クラスが必要です。
class DDLTYPE(std_string) {
public:
// mapping of DDL type to a C++ type
typedef std::string CPPType;
static void Add(Message* pMessageToSend,
const std::string& oString) {
// Code to add the string to the message.
}
static void Extract(Message* pReceivedMessage,
std::basic_string<C>* pString) {
// Code to extract the string from the message.
}
};
次のデータ型を定義して、ユーザー定義テンプレートを DDL データ型として統合することもできます。
type umap <T1, T2, ... >;
この後、次のようにテンプレートを実装します。 テンプレートに指定されたパラメータは CPPType ではなく、DDLType であることに注意してください。
template <class DDLKey, class DDLValue>
class DDLTYPE(umap) : public DDLType {
public:
typedef NS_QSTL Map<DDLKey::CPPType,
DDLValue::CPPType> CPPType;
static void Add(Message * pMessageToSend,
const CPPType &uMap){
(*pMessageToSend) << (qUnsignedInt32)uMap.size();
CPPType::const_iterator i;
CPPType::const_iterator end = uMap.end();
for( i = uMap.begin(); i != end; i++ ){
DDLKey::Add( pMessageToSend, (*i).first );
DDLValue::Add( pMessageToSend, (*i).second );
}
};
static void Extract(Message *pReceivedMessage,
CPPType *pUMap ){
qUnsignedInt32 uiSize;
(*pReceivedMessage) >> uiSize;
qUnsignedInt32 i;
for(i = 0; i < uiSize; i++){
DDLKey::CPPType k;
DDLValue::CPPType v;
DDLKey::Extract( pReceivedMessage, &k );
DDLValue::Extract( pReceivedMessage, &v );
(*pUMap)[k] = v;
}
};
}
カスタムデータ型のこの例の完全な実装は、製品に付属され、include/Extensions/STL ディレクトリに STL の拡張子で格納されています。 STL.ddl と STLTypes.h のファイルでは、.cpp は標準の C++ ビットセットと文字列を定義し、実装します。
カスタムデータ型が特定の変数に指定されている場合、開発者はメッセージへのストリーミングとメッセージからのストリーミングを実装して、 システムにデータの処理方法を示す必要があります。 このデータがステーション間で送信されると、システムはメッセージを作成するので、 開発者は Message クラスのメソッドを使用してデータを追加し、抽出する必要があります。 データはストリームオペレータまたは AddData メソッドおよび AddDataString メソッドを介してメッセージに追加できます。 これらのメソッドはそれぞれ、特定のデータ型または文字列のデータを追加します。 同様に ExtractData メソッドは、メッセージバッファからデータを抽出する際に使用されます。 メッセージコンテンツのサイズは GetPayloadSize で返すことができます。 GetLastError メソッドはクラスで生成された最後のエラーを返すので、ストリーム操作中にエラーが発生したかどうかを調べる際に特に便利です。 カスタムデータ型の実装例は製品に付属され、../include/Extensions/STL ディレクトリに STL の拡張子で格納されています。
15.1.1.4. 必須メソッド
カスタムデータ型を実装する際、開発者はユーザー実装の C++ クラスに次のメソッドを実装する必要があります。
- デフォルトコンストラクタ
- コンストラクタのコピー(特定の条件下に限り必要、以下を参照)
- 代入演算子: operator=
- 等価演算子: operator==
コンストラクタのコピーは次のいずれかの条件が満たされる場合のみに必要です。
- RMC の返り値型として次のカスタムデータ型が使用されている場合: Custom foo()
- カスタムデータ型を RMC に値として渡した場合。例: void foo(Custom toto)
カスタムデータ型を参照として渡しただけの場合は、コンストラクタのコピーは必要ありません。
15.1.1.5. クラスデータ型
カスタムのデータ型を定義する別の方法として、データ型をクラスとして宣言することができます。 これは場合によっては、実装を簡略化できることがあります。 クラスのデータ型を定義する際に使用する構文を次に示します。
class ClassName [: inheritance_class] {
class attributes
} [concrete];
class attributes は上述のように任意の数のデータ型になることができ、inheritance_class は ClassName が継承する別のクラス名を参照します。 この宣言から、DDL コンパイラは ClassNameDDL.h/.ccp ファイルと DDLCLASS(ClassName) クラスを生成し、ClassName クラスがそれを継承します。 ClassName クラスに機能を追加するには、クラスを独自に実装する必要があります。 機能を追加しない場合は、concrete プロパティを使用できます。 このプロパティが宣言されると、DDL コンパイラは宣言されたクラスに基本 C++ クラスを生成します。 このクラスは、メソッドを含まず、変更はできません。 例えば、DDL に次を宣言するとします。
class Request{
int32 m_intPlayerID;
byte m_byType;
} concrete;
DDLCLASS(Request) クラス、RequestDDL.h ファイル、RequestDDL.cpp ファイルが生成されます。 concrete プロパティが指定されると、Request クラスが RequestDDL.h/.cpp ファイル内で生成されるので、変更はできません。 concrete プロパティを使用しない場合、Request.h/.cpp ファイルを実装することが予期されます。
15.1.2. DDL プロパティ
次に NetZ の内蔵 DDL プロパティを示します。 このほとんどは、データセットの宣言のみで使用できます。 互換性のない唯一のプロパティは buffered と extrapolation_filter で、一緒に宣言することはできません。 このセクションで後述するとおり、独自のカスタム DDL プロパティを実装することもできます。
DDL プロパティはデータセットの更新方法を指定するために主に使用されます。 デフォルトでは、データセットの変数が変更されることを仮定しているので、 各デュプリカは DuplicatedObject::Update が呼び出されるたびに更新され、配信が保証されている信頼性のあるチャンネルでデータが送信されます。 これとは異なる方法でデータセットを更新するには、データセットの DDL 宣言に 1 つ以上の DDL プロパティを含める必要があります。
プロパティ | 使用場所 | 説明 |
---|---|---|
unreliable | Dataset | データセットの更新は信頼性のないチャンネルで送信されます。更新は信頼性のあるチャンネルを使用する送信より高速ですが、配信は保証されません。このチャンネルは、更新が失われてもゲームには弊害のない、位置などの頻繁に変更される変数を含むデータセットに向いています。信頼性のないチャンネルで送信されるデータセットには 3584Byte を超えるデータを含めることはできません。標準では重複したデータや順番が入れ替わったデータが到着する可能性があります。RootTransport:: |
buffered | Dataset | デュプリカのデータセットデータメンバーの値は直接更新されません。更新メッセージがデュプリカに受信されると、結果はバッファに保存されます。アプリケーションが DuplicatedObject:: |
Constant | Dataset | データセットデータメンバーの値が一定しています DO の作成時、データセット値がそのデュプリカに送信され、値が変更されない場合は更新されません。 |
update_ |
Dataset | DataSet:: |
upon_ |
Dataset | データセットの更新は、DataSet:: |
station_ |
Dataset | このプロパティは最適化のため、またはセキュリティ上の理由、またはその両方の理由からデータセットが更新されるステーションを絞り込む際に使用されます。このフィルタを指定するには、DataSet:: |
extrapolation_ |
Dataset | このプロパティは、予測アルゴリズムをデュプリカのデータセットメンバーの値に適用します。位置など、継続して変更するデータセットに向いています。NetZ では、データセットが通常継続して変更し、時折連続性が切断される場合があることを示すオプションも用意しています。推定フィルタを使用する場合、DuplicatedObject:: |
Loopback | Dataset | このプロパティはデータの内挿が、 DO マスターのデータセットメンバーの値に適用されることを示します。extrapolation_ |
Concrete | Dataset, class | このプロパティが宣言されると、DDL コンパイラは宣言されたデータセットに、メソッドを含まず、変更できない基本の C++ クラス(ソースファイルとヘッダーファイル)を生成します。このプロパティはデータセットクラスに機能を追加しない場合に使用します。機能を追加する場合には、このプロパティは指定しないでください。この場合、クラスを独自に実装する必要があります。 |
Globaldo | Doclass | すべての NetZ の DO クラスはグローバル DO として自動的にインスタンス化されます。グローバル DO は、セッション全体で認識され、セッションに参加する全ステーションへの複製が保証されています。 |
nonglobal | Doclass | 通常使用しません。(デフォルトではそのオブジェクトはグローバルになります。これを非グローバルにするには、DDL ファイルのクラス宣言に nonglobal プロパティを使用します。) |
15.1.3. カスタム DDL プロパティ
NetZ で提供されている DDL プロパティが要件に合わない場合、以下に説明するように、 独自のカスタムデータセットプロパティまたは DO プロパティを実装できます。 カスタムデータセットプロパティを使用すると、希望通りの方法でデータセットを更新でき、 カスタム DO プロパティを使用すると、カスタムコードを DDL で生成されたファイルに追加することができます。
15.1.3.1. データセット
独自のデータセット DDL プロパティを実装するには、次を行う必要があります。
- カスタムデータセット DDL プロパティを DDL ファイルに宣言します。
- dsproperty DDL 宣言で使用されるマクロを定義します。
- 1. カスタムデータセット DDL プロパティの宣言
カスタムデータセット DDL プロパティは、次の構文を使用して DDL ファイルに宣言する必要があります。
Code 15.9 カスタムデータセット DDL プロパティの宣言dsproperty PropertyName : <property qualifier>;
ここでは、PropertyName はカスタム DDL プロパティの名前です。property qualifier は DDL プロパティのデータ型を定義する識別子です。 指定されたプロパティの識別子は、次に説明する updatefilter または code になります。 カスタムデータセット DDL プロパティを宣言すると、通常の方法で該当するデータセットにそのプロパティを割り当てることができます。
- データセットのプロパティ識別子
dsproperty の宣言では、次のプロパティ識別子が指定できます。
Code 15.10 データセットのプロパティ識別子code
このプロパティ識別子を使用すると、特定の DO の DDL コンパイラで生成されたファイルにカスタムコードを追加できます。 生成されるコードでは、次の 4 つのマクロが使用されます。
Code 15.11 データセットのプロパティ識別子のコード生成で使用されるマクロ// public declaration _PR_PropertyName_pudecl() // private declaration _PR_PropertyName_prdecl() // source file implementation _PR_PropertyName_impl(DOCLASS) // source file implementation of a derived class _PR_PropertyName_derived_impl(DOCLASS,PARENT)
ここでは、PropertyName はカスタム DO DDL プロパティの名前です DOCLASS はプロパティを使用する複製オブジェクトクラスの名前です。 PARENT は DOCLASS が継承する複製オブジェクトクラスの名前です。
例えば、DDL ファイルで MyDO クラスを定義して code プロパティ識別子を指定するプロパティを使用する場合、 上の 4 つのマクロが DDL で生成される DATASET(MyDO) クラスで使用されます。 特に、最初の 2 つのマクロはそれぞれ MyDODDL.h ファイルのパブリック宣言とプライベート宣言で展開され、 後の 2 つのマクロは MyDODDL.cpp ファイルで展開されます。
- 2. マクロの定義
- 該当する DDL 宣言の作成が終わると、<DDLFileName>Properties.h ファイル内に、生成されたコードで使用される適切なマクロを定義する必要があります。 このマクロを使用して、該当する DDL プロパティを実装するクラスの名前を定義します。
15.1.3.2. DO
独自 DO DDL プロパティを実装するには、次を行う必要があります。
- カスタム DO DDL プロパティを DDL ファイルに宣言します。
- doclassproperty DDL 宣言で使用されるマクロを定義します。
- 1. カスタム DO DDL プロパティの宣言
カスタム DO DDL プロパティは、次の構文を使用して DDL ファイルに宣言する必要があります。
Code 15.12 カスタム複製オブジェクト DDL プロパティの宣言doclassproperty PropertyName : <property qualifier>;
ここでは、PropertyName はカスタム DDL プロパティの名前です。property qualifier は DDL プロパティのデータ型を定義する識別子です。 指定されたプロパティの識別子は、次に説明する code のみになります。
カスタム DO DDL プロパティを宣言すると、それを通常の方法で該当する DO に割り当てることができます。
- DO のプロパティ識別子
doclassproperty の宣言では、次のプロパティ識別子が指定できます。
Code 15.13 DO のプロパティ識別子code
このプロパティ識別子を使用すると、特定の DO の DDL コンパイラで生成されたファイルにカスタムコードを追加できます。生成されるコードでは、次の 4 つのマクロが使用されます。
Code 15.14 DO のプロパティ識別子のコード生成で使用されるマクロ// public declaration _PR_PropertyName_pudecl() // private declaration _PR_PropertyName_prdecl() // source file implementation _PR_PropertyName_impl(DOCLASS) // source file implementation of a derived class _PR_PropertyName_derived_impl(DOCLASS,PARENT)
ここでは、PropertyName はカスタム DO DDL プロパティの名前です DOCLASS はプロパティを使用する複製オブジェクトクラスの名前です。 PARENT は DOCLASS が継承する複製オブジェクトクラスの名前です。
例えば、MyDO クラスが code プロパティ識別子を指定するプロパティを使用することを DDL ファイルに定義する場合、 上の 4 つのマクロが DDL で生成される DATASET(MyDO) クラスで使用されます。 特に、最初の 2 つのマクロはそれぞれ MyDODDL.h ファイルのパブリック宣言とプライベート宣言で展開され、 後の 2 つのマクロは MyDODDL.cpp ファイルで展開されます。
- 2. マクロの定義
- 該当する DDL 宣言の作成が終わると、<DDLFileName>Properties.h ファイル内に、生成されたコードで使用される適切なマクロを定義する必要があります。 このマクロを使用して、該当する DDL プロパティを実装するクラスの名前を定義します。
15.1.4. アプリケーションタイトル
アプリケーションタイトルはゲームの種類を定義します。 アプリケーションタイトルはセッションに参加しようとするすべてのステーションの認証に使用されるため、DDL ファイルに定義する必要があります。 複数の DDL ファイルが使用される場合、他のすべての該当する DDL ファイルを含むか使用する DDL ファイルで、アプリケーションタイトルを定義する必要があります。 アプリケーションタイトルは、SessionDescription にも含まれます。 ゲームの種類の特定のインスタンスを識別する際に使用されるセッション名と混同しないようにしてください。 セッション名は、 6.1. で説明した Session::CreateSession メソッドを使用してセッションの作成時に定義されます。 アプリケーションタイトルとは異なり、セッション名の定義は必須ではありません。 DDL でアプリケーションタイトルを定義する際に使用される構文を次に示します。
title "string";
このため、ゲームのアプリケーションタイトルを SphereZ と定義するには、DDL ファイルに次の宣言を行います。
title "SphereZ";
15.1.5. DO クラス
マルチプレイヤーゲームでは、プレイヤーが相互に見えるようにセッションのオブジェクトをネットワーク全体で複製する必要があります。 オブジェクトの複製は、この複製のために NetZ で使用するメカニズムです。 NetZ の DO は DO クラス DOClasses)を使用して宣言されます DO は DO クラスのインスタンスで、同じ DO クラスの複数のインスタンスを作成することができます。
DO と DO クラスの関係は、標準の C++ プログラミングでのオブジェクトとクラスの関係と同様です。 C++ のオブジェクトと NetZ の DO 間の違いは、オブジェクトがインスタンス化される際に明白になります。 NetZ では DO クラスのインスタンスが特定のステーションで作成されるたびに、 そのオブジェクトが必要とされるすべてのリモートステーションにインスタンスのコピーが自動的に作成されます。 ローカルの DO は DO マスターと呼ばれる、コントロールするオブジェクトのインスタンスで、その他のオブジェクトはデュプリカです。
DO クラスは、各 DO の関連データセット、RMC、アクションの宣言が行われる DDL ファイルで宣言されます。 後続のセクションで詳細を説明します。
DDL ファイルで DO を宣言するには、次の構文を使用します。
doclass ObjectName [: inheritance_class] {
[declarations];
};
ここでは、[inheritance_class] は、ObjectName クラスが継承する他の DO クラスの名前を示します。 [declarations] は、クラスの関連データセット、RMC、アクションの宣言すべてです。
デフォルトでは、NetZ のすべてのオブジェクトはグローバルです。 そのため、DDL で定義される各クラスはセッション全体にグローバルで認識され、 セッションに参加する全ステーションに複製されることが保証されています。 (通常、これを非グローバルにする必要はありません)
また DO を WellKnown オブジェクトにすることもできます。 グローバル DO と WellKnownDO の違いは、 WellKnown オブジェクトはセッションの作成前に作成されることです。 ステーションがセッションに参加すると、Session::JoinSession メソッドがそのステーションに返る前に、 ステーションがすべての WellKnown オブジェクトを検出することが保証されています。 また、 WellKnown オブジェクトはデフォルトではフォルトトレラントで、 DO マスターのあるステーションに障害が発生するか、 セッションから離脱すると、新しいステーションに移行します。
特定の DO クラスの WellKnown インスタンスは、DDL ファイルで宣言されます DO が WellKnown オブジェクトとして宣言されると、 DDL コンパイラは、各ステーションの WKHandle 型のグローバル変数を宣言し、初期化します。 これは、オブジェクトに DOHandle を構築する際に使用できます。 これらのインスタンスは DuplicatedObject::CreateWellKnown を使用してセッションマスターに作成する必要があり、 セッションに属するすべてのステーションに複製されます。
wellknown DOClassName aVariableName;
例えば、SphereZ の例では DOClass World の WellKnown インスタンスを次のように作成します。
wellknown World g_hWorld;
World のインスタンスの 1 つは既知なので、DDL コンパイラで生成されるファイルには WKHandle 型のグローバル変数 g_hTheWorld が定義されます。 同様に、DDL で定義される各クラスには DOHandle 型の変数がコンパイラによって生成され、それは特定のクラスの DO を参照する際に使用されます。 WKHandle インスタンスは DOHandle クラスを継承します。 WellKnownDO クラスの実装の詳細については、 12.4. を参照してください。
次に架空の SphereZ サンプルプログラムの DDL の一部を示します。 GeometricalObject、Sphere、AISphere、World の 4 つの DO クラスが DDL で宣言されています。 これらの各 DOClasses にはデータセット、RMC、アクションが含まれます。 AISphere のデータセット、RMC、アクションは、Sphere クラスで定義されるデータセット、RMC、アクションを継承します。 Sphere クラスのデータセット、RMC、アクションは、GeometricalObject クラスで定義されるデータセット、RMC、アクションを継承します。 この例は、新しいコンセプトが説明されるたびにこのマニュアル全体で展開されます。
doclass GeometricalObject {
[declarations];
};
doclass Sphere : GeometricalObject {
[declarations];
};
doclass AISphere : Sphere {
[declarations];
};
doclass World {
[declarations];
};
wellknown World g_hWorld;
DDL ファイルで定義する各 DO クラスにソースファイルとヘッダーファイルを記述し、その後クラスを実装する必要があります。 詳細はそれぞれ、 15.5. と 12.1. を参照してください。
15.1.6. データセット
DDL でデータセットを定義する際に使用される構文を次に示します。
dataset DatasetName {
Dataset attributes;
}[Update Policy];
ここでは、Dataset attributes は、 15.1. に説明する任意の数の単純データ型にすることができます。 ただし、推定フィルタを使用する場合は、int、float、double のデータ型のみが使用できます。 [Update Policy] は、セクション 15.1. に説明するように、有効な DDL プロパティの任意の組み合わせを使用してデータセットを更新する方法を指定します。
複数の DDL プロパティが指定されている場合、各プロパティはコンマで区切る必要があります。
デフォルトでは、データセットの変数が変更されることを仮定しているので、 各デュプリカは DuplicatedObject::Update が呼び出されるたびに更新され、配信が保証されている信頼性のあるチャンネルでデータが送信されます。 これとは異なる方法でデータセットを更新するには、データセットの DDL 宣言に 1 つ以上の DDL プロパティを含める必要があります。
先に始めた SphereZ の例を続けると、DDL では Position、SphereData、Weather の 3 つのデータセットを定義します。 それぞれに使用される更新ポリシーを次に示します。
15.1.6.1. Position
このデータセットには、球体の位置を示す変数 x、y、z が含まれます。 予測アルゴリズムが Position データセットの更新に使用され、更新は信頼性のないチャンネルで送信されます。 推定フィルタは、NetZ にネットワーク更新間の x、y、z の値を予測するように指示し、データセット値のスムージングが行われるようにします。
15.1.6.2. SphereData
このデータセットは、球体の外観を定義する Texture 変数を含みます。 SphereData データセットの更新は信頼性のあるチャンネルで送信され、リクエストに応じてのみ更新されます。 このデータセットは頻繁には変更されませんが、オブジェクトにすべての変更が通知されることが重要です。
15.1.6.3. World
このデータセットには、霧のオンまたはオフを定義する FogEnabled 変数が含まれます。 World データセットの更新はデフォルトの更新ポリシーを使用して送信されます。 この場合更新は、データが変更されるたびに信頼性のあるチャンネルで送信されます。
dataset Position {
double x;
double y;
double z;
} unreliable, extrapolation_filter;
dataset SphereData {
uint16 m_ui16Texture;
} upon_request_filter;
dataset World {
int FogEnabled;
}
データセットが DDL で定義されると DO に関連付けられる必要があります。 例えば、Position データセットを GeometricalObject DO クラスに関連付けるには、次の構文を使用します。
doclass GeometricalObject {
Position m_dsPos;
// other declarations
};
Sphere DO クラスは GeometricalObject を継承するので、Sphere クラスは Position データセットを含みます。
データセットが DDL ファイルで宣言されると、 12.6. の説明に従って、ユーザーによって実装される必要があります。
15.1.6.4. MemberContainers
NetZ で使用されるコンテナは C++ の標準ライブラリのコンテナと非常に似ています。 コンテナの使用の詳細については、C++ プログラミングに関する優れた書籍を参照してください。 NetZ で使用されるコンテナの種類は、membervector、memberlist、memberqueue で、サポートされているコンテナのデータ型は string 型以外の上述のデータセット変数の型と同じです。 コンテナが DDL で宣言されると、デフォルト動作である信頼性のあるチャンネルで更新を送信し、さらに推定フィルタの使用は指定できないことを指示する必要があります。 例えば、3 つのコンテナを持ち、Avatar DO クラスに関連付けられている MyContainer データセットクラスは、次のように DDL で定義されます。
dataset MyContainer{
membervector<double> vec;
memberlist<dohandle> lst;
memberqueue<int32> que;
};
doclass Avatar{
MyContainer m_dsContainer;
};
ここで、TYPE は先に示されている <DDL dsts types> のいずれかです。 このコンテナのイテレータを作成するには、次を行います。
MyContainer::vecIterator
15.1.7. リモートメソッドコール
NetZ がリモートで DO にメソッドを呼び出す方法は、リモートメソッドコール(RMC)またはアクションを使用しますが、 これについてはこのセクションと 15.1.8. で説明します。 RMC は、 DO マスターまたはデュプリカになることができるオブジェクトの特定のインスタンスで呼び出すメソッドで、値を返すことができます。 RMC を使用すると、アクションを使用するよりも、呼び出される方法に関して、 また呼び出しの State と Outcome について開発者が取得する情報に関して、メソッドのコントロールが大幅に向上します。
リモートメソッドコールは、DDL ファイルに宣言され、パラメータを含むことができます。 宣言された各 RMC にはシステムから固有の MethodID が割り当てられます。 有効な引数は、 15.1. に示すデータセットに有効な引数と、有効なカスタムデータ型と同じです。 内蔵テンプレート型(MemberVector、MemberList、MemberQueue のいずれか)が RMC の引数として定義される場合、 NetZ ではユーザー定義の関数に次の形式のパラメータ型を使用する必要があります。
MemberVector <DDLTYPE(type)>,
MemberList <DDLTYPE(type)>,
or MemberQueue <DDLTYPE(type)>
RMC で使用する構文を次に示します。
returntype RMCName( [Argument List] );
ここでは、returntype は返り値のパラメータの型か void です。 [argument list] は、C++ 関数の宣言同様に任意の数の引数を取ることができます。
RMC の入出力の引数は、次の例のように in、out、in out の修飾子を使用して指定できます。 この例では、BestMatch、ListMatches、UpdateList の RMC を含む CarDealer DO クラスがあります。 最初の 2 つのメソッドはそれぞれ、車両のメーカー、モデル、年式、価格から構成される特定の条件に最も近い車両と、特定の条件を満たすすべての車両のリストを返します。 UpdateList メソッドは、有効な車両の現在のリストを更新します。
doclass CarDealer {
dohandle BestMatch(int32 imake, int32 imodel, int32 iyear, int32 iprice);
void ListMatches(int32 imake, int32 imodel, int32 iyear,
out int32 iNbOfCars, out dohandle hCarArray[16]);
void UpdateList(in out dohandle hCarArray[16]);
// other declarations
};
RMC が DDL ファイルで宣言されると、 14.1. で説明するとおり、ユーザーによって実装される必要があります。
15.1.8. アクション
NetZ が DO にリモートでメソッドを呼び出す方法では、上述のリモートメソッドコール(RMC)を使用するか、またはアクションを使用します。 アクションは DO クラス内で呼び出されるメソッドで、メソッドがオブジェクトの全デュプリカで実行されるようにオブジェクトにメソッドを呼び出すもっとも簡単な方法です。 ただし、RMC とは異なり、アクションは値を返すことができません。
アクションは、 DO マスターまたはオブジェクトのデュプリカで呼び出すことができます。 アクションが DO マスターで呼び出されると、 DO マスターは該当するメソッドをそのデュプリカすべてで呼び出します。 アクションがデュプリカで呼び出されると、そのデュプリカは、該当するメソッドをその DO マスターで呼び出します。 その後必要に応じて、 DO マスターはそのデュプリカのデータセットを更新します。
アクションは、DDL ファイルに宣言され、パラメータを含むことができます。 宣言された各アクションにはシステムから固有の MethodID が割り当てられます。 有効な引数は、 15.1. に示すデータセットに有効な引数と、有効なカスタムデータ型と同じです。 内蔵テンプレート型(MemberVector、MemberList、MemberQueue のいずれか)がアクションの引数として定義されると、 NetZ ではユーザー定義の関数に、MemberVector <DDLTYPE(type)>、MemberList <DDLTYPE(type)>、 MemberQueue <DDLTYPE(type)> のいずれかの形式のパラメータ型を使用する必要があります。
アクションに使用される構文を次に示します。 ここでは、[argument list] は、C++ 関数の宣言と同様に任意の数の引数です。
action ActionName( [Argument List] );
SphereZ では、天気の更新は DO クラス内で行われるアクションと同様に定義され、リモートで呼び出すことができます。 DDL ファイルの UpdateWeather アクションの宣言を次に示します。
doclass World {
// other declarations
action UpdateWeather();
};
アクションが DDL ファイルで宣言されると、 14.2. で説明するとおり、ユーザーによって実装される必要があります。
15.1.9. 定数
DDL と C++ コード間で共有できる定数を指定するには、#define ディレクティブが使用できます。 この場合、定数とその値を次のように定義する必要があります。 ConstantName は定数の名前で Value はその値です。
#define ConstantName Value
例えば、架空の MyConstant という定数を次のように定義できます。
#define MyConstant 15
定数を指定する DDL ファイルでは、特にファイルに定義されるすべてが定数の場合、 #include DDL プリプロセッサディレクティブを使用してファイルを含めるほうが、#use ディレクティブを使用するより通常簡単です。
15.2. DDL プリプロセッサディレクティブ
DDL 宣言は 1 つまたは複数の DDL ファイルに作成できます。 複数の DDL ファイルを使用する場合、#include と #use のプリプロセッサディレクティブを使用して、 すべての関連情報が DDL コンパイラで使用できるようにする必要があります。 通常プリプロセッサディレクティブは、ソースプログラムを変更しやすいように、 また異なる実行環境でコンパイルしやすいようにするために使用されます。 DDL プリプロセッサディレクティブは標準の C++ プログラミングと同様に機能します。
DDL プリプロセッサは次のディレクティブを認識します。
プロパティ | 説明 |
---|---|
#define マクロ | |
#define マクロ 文字列 | #define ディレクティブを使用すると、プログラムの定数に意味のある名前を指定できます。ただし、標準の C++ 構文とは異なり、マクロは引数を取ることができません。NETZ マクロが DDL コンパイラで自動的に定義されます。 |
#else | #else ディレクティブは #ifdef / #ifndef と #endif ディレクティブの間に使用できます。#else ディレクティブは 1 つに限り使用することが許可され、使用する場合は #endif の前の最後のディレクティブにする必要があります。 |
#endif | ソースファイルの #ifdef と #ifndef の各ディレクティブは終端の #endif ディレクティブと組み合わせる必要があります。 |
#ifdef 識別子 | |
#ifndef 識別子 | #ifdef ディレクティブは #else ディレクティブと #endif ディレクティブとともに使用してソースファイルの一部のコンパイルを制御します。この定数表現は、識別子が現在定義されている場合には真(非ゼロ)とみなされ、そうでない場合は条件が偽(ゼロ)とみなされます。#ifndef ディレクティブは #ifdef で確認された条件の反対を確認します。識別子が定義されていない場合、条件は真(非ゼロ)で、そうでない場合は条件が偽(ゼロ)になります。ソースファイルの各 #ifdef ディレクティブは終端の #endif ディレクティブと組み合わせる必要があります。#else ディレクティブは 1 つに限り使用することが許可され、使用する場合は #endif の前の最後のディレクティブにする必要があります。 |
#include <filename> | #include ディレクティブは、指定されているファイルのステートメントを、ディレクティブが指定されている点のソースプログラムにあるものとして処理するようにプリプロセッサに指示します。プリプロセッサはローカルディレクトリでファイルを検索し、その後 -I コンパイラオプションで指定されたパスに沿って検索し、最後にインストールディレクトリの Frameworks サブディレクトリを検索します。 |
#use <filename> | #use ディレクティブは、使用されている DDL ファイルで DDL コンパイラがクラスなどにコードを生成しないこと以外は、#include と同様に動作します。プリプロセッサはローカルディレクトリで使用するファイルを検索し、その後 -I コンパイラオプションで指定されたパスに沿って検索し、最後にインストールディレクトリの Frameworks サブディレクトリを検索します。 |
15.3. DDL コンパイラの使用
プロジェクトがコンパイルされると、DDL コンパイラは次のルールに従います。 このルールにより、コンパイラは生成されたファイルの場所を認識できます。
- DDL は、ファイルの内容が変更された場合にのみそのファイルを再生成します。これにより、変更されていないファイルは再コンパイルされないので、コンパイルが早くなります。
- DDL によって生成されたファイルは、関連付けられている DDL ファイルと同じディレクトリで常に生成されます。DDL ファイルに行われた定義のユーザー実装ファイルもこのディレクトリに必要です。
- DDL ファイルに別の DDL ファイルが含まれている場合、含まれている DDL の生成ファイルはそれを含むファイルのディレクトリに生成されます。つまり、含まれているファイルの内容は、それが含まれるファイルの一部としてコンパイルされます。
- DDL ファイルが別の DDL ファイルを使用する場合、生成されたファイルの #include 行のパスが、使用されるファイルのパスと同じになります。例えば、#use <path/MyFile.ddl> が DDL ファイルにある場合、#include 「path/MyFileDDF.h」 が生成されます。
- 生成されたファイルがローカル DDL からの別のファイルを含む必要がある場合、デフォルトでは #include 行のパスにはプレフィックスがありません。プレフィックスを指定するには、-includeprefix <path> コンパイラオプションを使用します。
DDL コンパイラを起動し、DDL に記述されるセッションのオブジェクトとデータセットを実装するのに必要なコードを生成するための構文を次に示します。
DDL.EXE [options] <filename>
ここでは、<filename> には DDL ファイル名を指定します。 このコマンドで使用できるオプションの詳細を次の表に示します。
オプション | 説明 |
---|---|
-D <macro> | 特定のマクロを定義します。 |
-header(または -p)<HeaderFilename> | 生成されるすべての .cpp ファイルの先頭に含まれるファイルを指定します。このオプションは事前にコンパイルされているヘッダーを持つプロジェクトに便利です。例えば、事前にコンパイルされているヘッダー stdheaders.h を使用する NetZ プロジェクトを構築する場合には、DDL コンパイラの起動時に -header stdheaders.h スイッチを使用します。 |
-help(または -h) | DDL コンパイラオプションの詳細を示すヘルプ画面を表示します。 |
-I <path> | DDL ファイルが別の DDL ファイルに含まれているか、使用されている場合に、ローカルディレクトリで検索するパスを指定します。通常このパスは C++ コンパイラにも渡されます。 |
-includeprefix <path> | 生成されるコードにファイルを含む必要がある場合に、プレフィックスとして使用するパスを指定します。例えば、ddl.exe -includeprefix Game MyFile.ddl が指定されている場合、#include 「Game/MyFileDDF.h」 が生成されます。 |
-nousingdirective | DDL コンパイラは、生成される各ファイルの先頭に NO_ |
-skeleton(または -g) | DDL コンパイラは DO クラス実装の開始点として使用できる、必要なユーザーファイルのスケルトンを生成します。既存のファイルが上書きされることはありません。 |
-verbose(または -v) | 詳細。 |
DDL コンパイラの返すエラーや警告のコードの詳細については、 16.3. を参照してください。 例えば、DDL ファイルの SphereZ.ddl をコンパイルするには、次の構文を使用します。
ddl.exe SphereZ.ddl
15.4. コンパイラ出力とクラス生成
NetZ で構築したアプリケーションをコンパイルする場合、DDL ファイルは NetZ の DDL コンパイラで使用され DOCLASS、DATASET、DUPSPACE の各クラスとそれに関するソースファイルとヘッダーファイルを生成します。 DDL ファイルから、コンパイラは DDL で行われた各データセットと DO 宣言にソースファイルとヘッダーファイルの ClassNameDDL.cpp と ClassNameDDL.h を生成します。 その後生成されたクラスとファイル、およびユーザー実装のクラスとゲームコード、NetZ ライブラリが C++ コンパイラで使用され、実行ファイルが生成されます。 これを次の Figure 15.1 に示します。

Figure 15.1 実行ファイルの生成
15.4.1. C++ クラスの生成
NetZ の DDL コンパイラは、DDL ファイルで宣言されている記述に対応する C++ クラスを生成します。 NetZ の主なユーザー実装クラスは DO 、データセットクラスです。 これらのユーザー実装クラスは DDL コンパイラによって生成されたクラスを継承し、このクラスは NetZ の DuplicatedObject クラスと DataSet クラスを継承します。 このクラス階層を Figure 15.2 に示します。

Figure 15.2 DO とデータセットの一般的なクラス継承図
15.4.1.1. 実装
通常、DDL に UserDOClass DO クラスを指定すると、DDL で生成されるクラスを継承する UserDOClass クラスを実装する必要があります。 この生成されたクラスには DOCLASS(UserDOClass) を使用してアクセスできます。 この場合 DOCLASS は生成されたクラスを参照する名前を構築するマクロです。 DDL ファイルでの DOClass 宣言の結果生成されたすべてのクラスは、最終的には DuplicatedObject ルートクラスを自動的に継承します。 DuplicatedObject クラスは DataSet クラスとは異なり、ユーザー実装クラス間の継承を DDL に指定できます。
同様に、DDL に指定されている UserDataSet データセットを指定する場合、DDL 生成クラスを継承する UserDataSet クラスを実装する必要があります。 この生成されたクラスには DATASET(UserDataSet) を使用してアクセスできます。 この場合、DATASET は生成されたクラスを参照する名前を構築するマクロです。 DDL で生成されたクラスは、最終的には DataSet ルートクラスを自動的に継承します。 UserDataSet クラスの一部として宣言された変数は、生成されたクラスの DATASET(UserDataSet) に宣言された変数を継承します。
15.4.1.2. インスタンス化
DO 、データセットのいずれも、直接インスタンス化はできません DO は DuplicatedObject::Create メソッドを使用して作成します。 このメソッドはパブリッシュ可能なクラスのインスタンスを作成します。 データセットは直接インスタンス化される必要はありません。 これは、データセットは DDL ファイルの宣言に従って NetZ によって自動的に実装されるためです。 データセットクラスでは、DDL で生成されたコードがクラスをメンバー変数として実装します。
DO には、DDL コンパイラで生成されたクラスがすべてのネットワークコードをカプセル化します。 このコードは、クラスのインスタンス化方法、 すべてのリモートステーションで検出されることの保証方法 DO の変数が変更されるとそのデュプリカが適切に更新されることの保証方法、 RMC またはアクションが呼び出される際にリモートでメソッドを呼び出す方法を指定します。 ユーザー実装のクラスはデータセット変数を宣言し、宣言された RMC とアクションに該当するメソッドを実装し、 またアプリケーションに関するローカル変数またはメソッドを追加することもできます。
同様にデータセットには、DDL コンパイラによって生成されるクラスがデータセット変数を保持し、 データのマーシャリング、アンマーシャリング、ストリーミングを含む、データセットの更新を担当します。 データセットの更新に推定フィルタが使用される場合、予測モデルも生成されます。 ユーザー実装されたクラスは、ゲームに適用可能なローカル変数またはメソッドを追加します。 このローカル情報はリモートステーションには意味がないので、複製されません。
15.4.1.3. SphereZ サンプルの理解
前のセクションでは、SphereZ の例の DO 、データセット、アクションを定義しました。 その結果、SphereZ の完全な DDL ファイルは次のようになります。
title “SphereZ”
dataset Position {
double x;
double y;
double z;
} extrapolation_filter, unreliable;
dataset SphereData {
uint16 m_ui16Texture;
} upon_request_filter;
dataset Weather {
int FogEnabled;
};
doclass GeometricalObject {
Position m_dsPos;
};
doclass Sphere : GeometricalObject {
SphereData m_dsSphereData;
};
doclass Sphere : AISphere {
};
doclass World {
Weather m_dsWeather;
action UpdateWeather();
};
wellknown World g_hWorld;
上の DDL ファイルの記述による DO とデータセットのクラス継承をそれぞれ Figure 15.3 と Figure 15.4 に示します。 ユーザー定義の DO クラス AISphere は Sphere クラスを継承し、Sphere クラスは GeometricalObject クラスを継承し、GeometricalObject クラスは NetZ の DuplicatedObject クラスを継承します。 同様に、ユーザー定義のデータセットクラス Position は NetZ の DataSet クラスを自動的に継承します。

Figure 15.3 DO のクラス継承

Figure 15.4 データセットのクラス継承
DDL で定義される各クラスについて、クラスの継承は該当するヘッダーファイルに定義されます。 この例では、AISphere.h ファイルは、AISphere クラスが DDL で生成された DOCLASS(AISphere) を継承することを定義します DOCLASS(AISphere) は DDL ファイルの定義から生成されます。 生成されたファイルには AISphereDDL.h の名前が指定されます。 同様に、DDL は DOCLASS(Sphere) クラスと DOCLASS(GeometricalObject) クラス、SphereDDL.h ファイルと GeometricalObjectDDL.h ファイルを生成します。 GeometricalObject クラスは最終的に NetZ の DuplicatedObject クラスを継承します。 該当するユーザークラスを定義する前に、DDL で生成されたヘッダーファイルを含める必要があります。 コンパイラは、定義された各クラスに該当するソースファイルも生成します。 これは、他のクラスにリンクされ、プロジェクトでコンパイルされる必要があります。 例えば、この例の DDL で生成されたソースファイルは AISphere.cpp、SphereDDL.cpp、GeometricalObjectDDL.cpp、WorldDDL.cpp です。
Position データセットは Position.h ファイルに定義されています。 Position データセットクラスは DDL で生成されたクラス DATASET(Position) を継承し、最終的には NetZ の DataSet クラスを自動的に継承します。 Position クラスの一部として宣言された変数は、生成されたクラスの DATASET(Position) に宣言された変数を継承します。 DDL によって生成されたファイルの名前は PositionDDL.h と PositionDDL.cpp です。 上述のとおり、ユーザーは該当するユーザークラスが定義される前に生成されたヘッダーファイルを含み、ソースファイルをプロジェクトでコンパイルする必要があります。
DO がインスタンス化されると DOClass 宣言に該当するメンバー変数は、DDL コンパイラで生成されたクラスではなく、開発者の独自のクラスを使用します。 例えば、DDL コンパイラで生成された DOCLASS(GeometricalObject) は、DATASET(Position) ではなく、Position 型の変数 m_dsPos を含みます。 そのため、Position クラスに追加されたコードは DO がインスタンス化される際に使用可能になります。 この状況を次の Figure 15.5 に示します。

Figure 15.5 DO とデータセットクラス間の関係
15.4.1.4. 継承
DDL で定義される各クラスに関するクラスの継承は、該当するヘッダーファイルに定義されます。 この例では、Moderator.h ファイルは、Moderator クラスが DDL で生成された DOCLASS(Moderator) を継承することを定義します DOCLASS(Moderator) は DDL ファイルの定義から生成されます。 生成されたファイルには ModeratorDDL.h の名前が指定されます。 同様に、DDL は DOCLASS(Delegate) DOCLASS(Sage) DOCLASS(Room) DOCLASS(SageBalancing) のクラス、DelegateDDL.h、SageDDL.h、RoomDDL.h、SageBalancing.h のファイルを生成します。 その後 Moderator クラスは Delegate クラスを継承し、最終的には NetZ の DuplicatedObject クラスを継承します。 該当するユーザークラスを定義する前に、DDL で生成されたヘッダーファイルを含める必要があります。 コンパイラは、定義された各クラスに該当するソースファイルも生成します。 これは、他のクラスにリンクされ、プロジェクトでコンパイルされる必要があります。 例えば、この例の DDL で生成されたソースファイルは DelegateDDL.cpp、ModeratorDDL.cpp、SageDDL.cpp、RoomDDL.cpp、SageBalancingDDL.cpp です。
Location データセットは Location.h ファイルで定義されます。 クラスは DDL で生成された DATASET(Location) クラスを継承し、最終的には NetZ の DataSet クラスを自動的に継承します。 クラスの一部として宣言された変数は、生成されたクラスの DATASET(Location) に宣言された変数を継承します。 DDL で生成されたファイルの名前は LocationDDL.h と LocationDDL.cpp です。 同様に DDL は、StringInfo データセットと SageKnowledge データセットに該当する、ファイル StringInfoDDL.h、StringInfoDDL.cpp、SageKnowledgeDDL.h、SageKnowledgeDDL.cpp を生成します。 通常どおり、ユーザーは該当するユーザークラスが定義される前に生成されたヘッダーファイルを含み、ソースファイルをプロジェクトでコンパイルする必要があります。
DO がインスタンス化されると DOClass 宣言に該当するメンバー変数は、DDL コンパイラで生成されたクラスではなく、開発者の独自のクラスを使用します。 例えば、DDL コンパイラで生成された DOCLASS(Location) は、DATASET(Location) ではなく、Location 型の変数 m_dsLocation を含みます。 そのため、次の Figure 15.6 のように Location クラスに追加されたコードは DO がインスタンス化されると使用可能になります。

Figure 15.6 DO とデータセットクラスの関係
15.5. 開発者の責任
NetZ で構築されたアプリケーションをコンパイルするには、開発者はファイルをいくつか実装する必要があります。 これが、この章で前述した方法で DDL ファイルを記述する開発者の責任です。 また、DDL で行った dataset、doclass、dupspace の各宣言に対して、.h ファイルと .cpp ファイルを実装する必要もあります。 ヘッダーファイルでは、クラスの継承と変数を定義する必要があり、さらにローカルの処理で使用されるデータセット以外の変数の定義も必要です。
DDL コンパイラで生成されるファイルがプロジェクトに正しくリンクされることも確実にする必要があります。 この作業を行うには、DDL で生成するすべてのヘッダーファイル(ClassNameDDL.h)が、クラスが定義される前に含まれており 、DDL で生成するすべてのソースファイル(ClassNameDDL.cpp)がリンクされ、プロジェクトでコンパイルされていることを確認する必要があります。
DDL ファイルで宣言されるクラスはすべて実装する必要があります。 つまり、すべてのデータセットに関連付けられているメソッド、リモートメソッドコールまたはアクションに関連付けられている照合関数の実装が必要です。 DO 、データセットのクラスのためのヘッダーファイルでのクラス宣言に使用する構文を次に示します。
class DuplicatedObjectName : public DOCLASS(DuplicatedObjectName) {
// User specified RMCs, actions, and methods
};
class DataSetName : public DATASET(DataSetName) {
// User specified methods
};
データセット、RMC、アクションに関連付けられているメソッドの実装も必要です。 例えば、GeometricalObject ヘッダーファイルの DO クラスの GeometricalObject を宣言するには、次の構文を使用します。
class GeometricalObject : public DOCLASS(GeometricalObject) {
// User specified RMCs, actions, and methods
};
すべての NetZ システムクラスは NEX 名前空間で定義されます。 デフォルトでは、NetZ を含む場合、システムは NEX 名前空間を使用します。 名前の競合を避ける場合など、NEX 名前空間を使用しない場合は、-nousingdirective DDL コンパイラオプションを使用して、 NetZ を含める前、またはコマンドラインから渡す前に、NO_USING_QUAZAL_DIRECTIVE マクロを定義します。
該当するコードをソースファイルとヘッダーファイルに実装すると、NetZ のシステムデフォルトを変更することができます。 例えば、オブジェクトがフォルトトレラントであるかどうか、移行可能かどうか、または推測航法の実装がカスタマイズできるかどうかを指定できます。
15.6. STL データ型
データ操作を容易にするため、プロジェクトのコンパイル時に含むことができる追加のデータ型がいくつか NetZに含まれています。 特に、次の C++ STL 文字列の実装とビットセットデータ型が提供されています。
DDL | C++ | コメント |
---|---|---|
string | String | qChar16*(8 ビット文字または 16 ビット文字の文字列のポインタ)を使用して内部で実装されます。NetZ では、RMC に配置すると、このような文字列を UTF-8 に変換します。 |
cstr | qChar | qChar16 にマッピングします。RMC に配置されても UTF-8 には変換されません。 |
qchar8 | qchar8 | |
qchar16 | Qchar16 | |
std_ |
qChar8* | RMC に配置されても UTF-8 には変換されません。 |
std_ |
qChar16* | RMC に配置されても UTF-8 には変換されません。 |
std_ |
std:: |
|
std_ |
std:: |
|
std_ |
std:: |
|
qlist<T> | qList<T> | T がデータ型(int など)です。 |
qvector<T> | qVector<T> | T がデータ型(int など)です。 |
qmap<Key, Value> | qMap<Key, Value> | <Key, Value> はマップ項目のキーと値です。 |
qqueue<T> | qQueue<T> | T がデータ型(int など)です。 |
std_ |
std:: |
T がデータ型(int など)です。 |
std_ |
std:: |
T がデータ型(int など)です。 |
std_ |
std:: |
<Key, Value> はマップ項目のキーと値です。 |
上の STL データ型をプロジェクトに統合するには、次を使用して STL.ddl ファイルをプロジェクトの DDL ファイルに含める必要があります。
#include <Extensions/STL.ddl>