プラグインフレームワークを自分で書く(13)
4396 ワード
では、前の章で欠けている部分を補いましょう.この部分の最後に、完全なコードが得られます.
モンスターカード
前に説明したプラグインフレームワークに基づいて、わざと4つの異なるタイプのプラグインを作成しました.純C++プラグイン 純Cカード 動的/共有ライブラリとして配備されたハイブリッドプラグイン は、実行可能ファイルのC++スタティックプラグイン に直接リンクすべきである.
これらのプラグインはすべて、そのモンスターオブジェクトをactorとしてPluginManagerに登録します.また,ゲーム自体にはHero類が提供されており,IActorインタフェースを実現した対象としている.ゲームによって制御されるHero類と他のモンスターオブジェクトのほとんどのIActorインタフェースのコードは一致している.ゲームには内蔵のモンスターも提供されます.
動的C++プラグイン
ダイナミックC++カードにはKillerBunnyとStationarySatanの2種類のモンスターが登録されています.次のコードはKillerBunnyです.hヘッダファイル.KillerBunnyはC++IActorインタフェースを直接実現した(これにより純粋なC++プラグインになった).PluginManagerのオブジェクトの作成と破棄に使用するcreate()とdestroy()static関数を実現します.StationarySatanおよび他の純粋なC++プラグインオブジェクトは基本的に類似しています(privateデータを除く).
次のコードにはcreate()とdestroy()の実装が含まれています.これらはすべて簡単です.create()関数は、新しいKillerBunnyオブジェクトを作成し、それを返します(voidポインタの形式).destroy()関数には、create()関数が返すvoidポインタをパラメータとして必要とします.voidポインタをKillerBunnyポインタに変換しdeleteが落ちます.ここで最も重要な部分は、PluginManagerがKillerBunnyクラスに関する情報を「知る」必要がなく、KillerBunnyオブジェクトを作成できるようにすることです.返されるインスタンスは、voidポインタが返されている場合でもIActorインタフェースで使用できます.
次のコードにはIActorインタフェースの実装が含まれています.これらの関数も簡単です.getInitialInfo()関数は、いくつかのデータを使用してActorInfo構造を組み立てるために使用されます.Play()関数こそ、KillerBunnyが実際に提供する機能です.移動、攻撃、回避などです.ここではITurnインタフェースから友軍のリストを取得するだけです.これは私たちが完全な実現を提供する必要がないからです.実際には、私たちの怪物は何もできません.Heroだけが本当の攻撃をすることができる.モンスターが攻撃を受けると、自分を守り反撃する必要があります.
これらのコードを書く目的は、純粋なC++プラグインを書くのがどんなに簡単かを実証することです.公式化されたcreate()とdestroy()static関数を除いて、標準的なC++クラスを実現するだけで、神秘的なコードを追加する必要はありません.
次はプラグイン初期化コードです.これらのコードは複雑ではありませんが、煩雑でエラーが発生しやすいです.PF_InitPlugin関数では、終了関数とPF_を定義します.RegisterParams構造体を組み立て、すべてのプラグインオブジェクトを登録します.初期化に失敗したときにNULLが返されることを確認します.それ以外に何もありません.これが純粋なC++モンスタープラグインを作成するために必要です(以下のコードでは、2つのモンスターを登録しています).
モンスターカード
前に説明したプラグインフレームワークに基づいて、わざと4つの異なるタイプのプラグインを作成しました.
これらのプラグインはすべて、そのモンスターオブジェクトをactorとしてPluginManagerに登録します.また,ゲーム自体にはHero類が提供されており,IActorインタフェースを実現した対象としている.ゲームによって制御されるHero類と他のモンスターオブジェクトのほとんどのIActorインタフェースのコードは一致している.ゲームには内蔵のモンスターも提供されます.
動的C++プラグイン
ダイナミックC++カードにはKillerBunnyとStationarySatanの2種類のモンスターが登録されています.次のコードはKillerBunnyです.hヘッダファイル.KillerBunnyはC++IActorインタフェースを直接実現した(これにより純粋なC++プラグインになった).PluginManagerのオブジェクトの作成と破棄に使用するcreate()とdestroy()static関数を実現します.StationarySatanおよび他の純粋なC++プラグインオブジェクトは基本的に類似しています(privateデータを除く).
#ifndef KILLER_BUNNY_H
#define KILLER_BUNNY_H
#include <object_model/object_model.h>
struct PF_ObjectParams;
class KillerBunny : public IActor
{
public:
// static plugin interface
static void * create(PF_ObjectParams *);
static apr_int32_t destroy(void *);
~KillerBunny();
// IActor methods
virtual void getInitialInfo(ActorInfo * info);
virtual void play(ITurn * turnInfo);
private:
KillerBunny();
};
#endif
次のコードにはcreate()とdestroy()の実装が含まれています.これらはすべて簡単です.create()関数は、新しいKillerBunnyオブジェクトを作成し、それを返します(voidポインタの形式).destroy()関数には、create()関数が返すvoidポインタをパラメータとして必要とします.voidポインタをKillerBunnyポインタに変換しdeleteが落ちます.ここで最も重要な部分は、PluginManagerがKillerBunnyクラスに関する情報を「知る」必要がなく、KillerBunnyオブジェクトを作成できるようにすることです.返されるインスタンスは、voidポインタが返されている場合でもIActorインタフェースで使用できます.
void * KillerBunny::create(PF_ObjectParams *)
{
return new KillerBunny();
}
apr_int32_t KillerBunny::destroy(void * p)
{
if (!p)
return -1;
delete (KillerBunny *)p;
return 0;
}
次のコードにはIActorインタフェースの実装が含まれています.これらの関数も簡単です.getInitialInfo()関数は、いくつかのデータを使用してActorInfo構造を組み立てるために使用されます.Play()関数こそ、KillerBunnyが実際に提供する機能です.移動、攻撃、回避などです.ここではITurnインタフェースから友軍のリストを取得するだけです.これは私たちが完全な実現を提供する必要がないからです.実際には、私たちの怪物は何もできません.Heroだけが本当の攻撃をすることができる.モンスターが攻撃を受けると、自分を守り反撃する必要があります.
void KillerBunny::getInitialInfo(ActorInfo * info)
{
::strcpy((char *)info->name, "KillerBunny");
info->attack = 10;
info->damage = 3;
info->defense = 8;
info->health = 20;
info->movement = 2;
// Irrelevant. Will be assigned by system later
info->id = 0;
info->location_x = 0;
info->location_y = 0;
}
void KillerBunny::play(ITurn * turnInfo)
{
IActorInfoIterator * friends = turnInfo->getFriends();
}
これらのコードを書く目的は、純粋なC++プラグインを書くのがどんなに簡単かを実証することです.公式化されたcreate()とdestroy()static関数を除いて、標準的なC++クラスを実現するだけで、神秘的なコードを追加する必要はありません.
次はプラグイン初期化コードです.これらのコードは複雑ではありませんが、煩雑でエラーが発生しやすいです.PF_InitPlugin関数では、終了関数とPF_を定義します.RegisterParams構造体を組み立て、すべてのプラグインオブジェクトを登録します.初期化に失敗したときにNULLが返されることを確認します.それ以外に何もありません.これが純粋なC++モンスタープラグインを作成するために必要です(以下のコードでは、2つのモンスターを登録しています).
#include "cpp_plugin.h"
#include "plugin_framework/plugin.h"
#include "KillerBunny.h"
#include "StationarySatan.h"
extern "C" PLUGIN_API apr_int32_t ExitFunc()
{
return 0;
}
extern "C" PLUGIN_API PF_ExitFunc PF_initPlugin(const PF_PlatformServices * params)
{
int res = 0;
PF_RegisterParams rp;
rp.version.major = 1;
rp.version.minor = 0;
rp.programmingLanguage = PF_ProgrammingLanguage_CPP;
// Register KillerBunny
rp.createFunc = KillerBunny::create;
rp.destroyFunc = KillerBunny::destroy;
res = params->registerObject((const apr_byte_t *)"KillerBunny", &rp);
if (res < 0)
return NULL;
// Regiater StationarySatan
rp.createFunc = StationarySatan::create;
rp.destroyFunc = StationarySatan::destroy;
res = params->registerObject((const apr_byte_t *)"StationarySatan", &rp);
if (res < 0)
return NULL;
return ExitFunc;
}