BREW コールバック関数の登録と呼び出し(JPEG 画像データを読み込んで表示する方法)
BREW ネイティブのコールバック関数を登録し、呼び出すためのサンプルコードです。
ファイルストレージまたはメモリストレージに保存された JPEG 画像データを読み込んで表示するコードを以下に記します。
BREW の仕様では、JPEG 画像データの表示処理は、ファイルストレージまたはメモリストレージに保存された JPEG 画像データの読み込みが完了したときに呼び出されるコールバック関数内に記述する必要があります。
ファイルストレージまたはメモリストレージに保存された JPEG 画像データを読み込むためのストリームは、 SFBImage::SetStream() 関数を使って設定します。
コールバック関数は SFBImage::Notify() 関数を使って登録します。
なお、コールバック関数を登録する SFBImage 型のインスタンス変数は jpegreader クラスの変数として登録します。メンバ関数などローカル変数として登録すると、スマートポインターで管理されるため変数スコープから外れたときに、メモリは自動的に解放され、コールバック関数が呼び出されません。
また、コールバック関数の実体は、ダミーのコールバック関数内から呼び出されます。コールバック関数の登録では、ダミーのコールバック関数を登録します。
■クラスの定義
SFMTYPEDEFCLASS(jpegreader)
class : public SFYApplication {
SFMSEALCOPY(jpegreader)
private:
SFBImageSmp _image;
public:
static SFCInvokerPtr Factory(Void);
private:
explicit jpegreader(Void) static_throws;
virtual ~jpegreader(Void);
SFCError LoadImage(SFXPathConstRef path);
SFCError ExampleDirectFile(SFXFilePtr file);
SFCError ExampleThroughMemory(SFXFilePtr file, UInt32 size);
XANDLER_DECLARE_BOOLEVENT(OnKey)
// コールバック関数の実体
Void OnImage(Void);
// ダミーのコールバック関数
friend Void read_finished(VoidPtr, IImage*, AEEImageInfo*, SIntN);
};
※注意:
1.JPEG 画像データを読み込む変数 _image は、クラス変数として定義します。JPEG 画像データを読み込むためのメンバ関数 LoadImage() 内のローカル変数として定義すると、JPEG 画像データの読み込み完了時に自動的に解放されるため、JPEG 画像を表示するためのダミーのコールバック関数 read_finished() が呼び出されません。
2.JPEG 画像を表示するためのダミーのコールバック関数 read_finished()は、friend 関数として定義します。
3.JPEG 画像を表示する実際の処理は、jpegreader::OnImage() 関数に記述します。このメンバ関数は、ダミーのコールバック関数 read_finished() から呼び出されます。
■クラスの実装
// パスから JPEG 画像データを読み込む
SFCError jpegreader::LoadImage(SFXPathConstRef path)
{
SFXFile file;
UInt32 size;
SFCError error(SFERR_NO_ERROR);
if ((_image = SFBImage::NewInstance(AEECLSID_JPEG, &error)) != null) {
if ((error = file.OpenReadOnly(path)) == SFERR_NO_ERROR) {
if ((error = file.GetSize(path, &size)) == SFERR_NO_ERROR) {
// ファイルストレージから JPEG 画像を読み込む場合
// ExampleDirectFile(&file);
// メモリストレージから JPEG 画像を読み込む場合
ExampleThroughMemory(&file, size);
}
}
}
return error;
}
// ファイルストレージから JPEG 画像データを読み込む
SFCError jpegreader::ExampleDirectFile(SFXFilePtr file)
{
// ダミーのコールバック関数を登録する
_image->Notify((PFNIMAGEINFO)read_finished, this);
// ファイルストレージのストリームを設定する
return _image->SetStream(*file);
}
// メモリストレージから JPEG 画像データを読み込む
SFCError jpegreader::ExampleThroughMemory(SFXFilePtr file, UInt32 size)
{
SFXBuffer buffer;
VoidPtr ptr;
SFXMemory memory;
SFCError error(SFERR_NO_ERROR);
if (size > 0) {
if ((error = buffer.SetSize(size)) == SFERR_NO_ERROR) {
ptr = buffer.Detach();
if ((error = file->Read(ptr, &size)) == SFERR_NO_ERROR) {
if ((error = buffer.Attach(ptr, size)) ==SFERR_NO_ERROR) {
if ((error = memory.Open(buffer)) == SFERR_NO_ERROR) {
// ダミーのコールバック関数を登録する
_image->Notify((PFNIMAGEINFO)read_finished, this);
// メモリストレージのストリームを設定する
error = _image->SetStream(memory);
}
}
}
}
}
else {
error = SFERR_FAILED;
}
return error;
}
// 実際のコールバック関数(実体: JPEG 画像を描画する)
Void jpegreader::OnImage(Void)
{
SFXRectangle rx;
AEEImageInfo info;
rx.Set(GetLocalBound());
_image->GetInfo(&info);
// JPEG 画像を描画する
_image->Draw((rx.GetWidth()-info.cx)/2, (rx.GetHeight()-info.cy)/2);
return;
}
// ダミーのコールバック関数(PFNIMAGEINFO 型)
Void read_finished(VoidPtr reference, IImage* /* image*/, AEEImageInfo* /* info*/, SIntN /* error*/)
{
// 実際のコールバック関数を呼び出す
static_cast<jpegreaderPtr>(reference)->OnImage();
return;
}
※注意:
4.JPEG 画像表示処理の実体は、ダミーのコールバック関数 read_finished() から呼び出される実際のコールバック関数 jpegreader::OnImage() 内に実装します。
5.JPEG 画像データを読み込むためのファイルストレージまたはメモリストレージを SFBImage::SetStream() 関数を使って設定し、SFBImage::Notify() 関数を使ってダミーのコールバック関数 read_finished() を登録します。
□サンプルコードダウンロード( jpegreader.zip: 99.7kb )
□関連情報:BREW FAQ : JPEG 形式で保存した画像ファイルを読み込むには?
ラッパー クラスの作成方法
BREW インターフェースには、ISHELL_CreateInstance() 関数でインスタンスを生成するインターフェース、IQI_QueryInterface() 関数でインスタンスを生成するインターフェース、 他の BREW インターフェースによってインスタンスを生成するインターフェースの 3 種類があります。
ラッパー クラスの作成は、ラッパー クラスの定義とそのメンバー関数の実装からなります。
それぞれのラッパー クラスの作成で異なるのはインスタンスの生成方法です。
詳細は、SophiaFramework リファレンスのラッパー クラスの作成方法をご覧ください。
SFXBrewPointer クラスの使用方法
SFXBrewPointer クラスは BREW インターフェースのインスタンスを自動管理するためのスマート ポインター クラスです。このクラスはテンプレート クラスとなっており、ラッパー クラスの種類だけ自動的に型が生成されます。
ラッパー クラスのインスタンスは、スマート ポインターで自動的に管理されますので、 SFXBrewPointer クラスを明示的に使用する必要はありません。
以下のようにして、明示的に型を生成することも可能です。
■
SFXBrewPointer クラスの使用方法
Void SFXPointerExplainer::_SFXBrewPointer(Void) const
{
// 以下の 2 種類の変数宣言は同等
// ( 通常、記述しやすい Smp バージョンを利用する )
SFXBrewPointer<SFBDisplay> display1;
SFBDisplaySmp display2;
// ラッパー クラスのインスタンスの生成は、
// 各ラッパー クラスの NewInstance() 関数または
// GetInstance() 関数を利用する
// ( スマート ポインターがインスタンスを管理するので、解放処理は不要 )
SFBGraphicsSmp graphics;
SFBGraphicsPtr raw_graphics;
if ((graphics = SFBGraphics::NewInstance()) != null) {
// インスタンスの取得成功
}
// 管理しているインスタンスの生ポインターの取得
raw_graphics = graphics.Get();
// スマート ポインターの比較
if (display1 == display2) {
}
if (display1 != display2) {
}
// スマート ポインターと生ポインターの比較
if (graphics == raw_graphics) {
}
// null ポインターとの比較
if (graphics != null) {
}
// 他の型を表すスマート ポインター同士の比較
// ( 推奨されないが、設計上可能 )
if (graphics != display1) {
}
// スマート ポインターが管理するインスタンスのポインターのキャストは、
// static_pointer_cast 演算子などを利用する
// ( static_cast 演算子を利用してはいけない )
SFBBaseSmp base;
SFBBitmapSmp bitmap;
base = bitmap;
bitmap = static_pointer_cast<SFBBitmap>(base);
// 空インスタンスの取得
// ( 関数の戻り値として空のインスタンスへの参照を返す場合に便利 )
SFBFileSmpConstRef file(SFBFileSmp::EmptyInstance());
unused(file);
// 管理しているインスタンスの明示的な解放
SFBFileMgrSmp filemgr;
if ((filemgr = SFBFileMgr::NewInstance()) != null) {
// SFXBrewPointer クラスの Release() 関数を呼び出す
filemgr.Release();
// SophiaFramework 3.0 以上では
// SFBBase (IBase) クラスの AddRef(), Release() 関数を呼び出せない
/*
filemgr->Release();
*/
}
return;
}
コールバック関数の登録方法
BREW インターフェース ラッパーで設定できるコールバック関数は、宣言・実装・登録を独自に行う必要があります。
以下のサンプル コードのように、内部コールバック関数を経由して、実際のコールバック関数を呼び出します。
SFBCamera クラスのコールバック関数の宣言・実装・登録
SFMTYPEDEFCLASS(Camera)
class Camera {
SFMSEALCOPY(Camera)
private:
// ICamera インターフェースのラッパークラス
SFBCameraSmp _camera;
public:
// カメラの基本的な初期化処理
SFCError Resume(Void);
// コールバック関数
static Void OnCameraSHP(VoidPtr reference, AEECameraNotify* notify);
// 実際のコールバック関数
Void OnCamera(AEECameraNotify *notify);
};
#endif
// カメラの基本的な初期化処理
SFCError Camera::Resume(Void)
{
SFCError error(SFERR_NO_ERROR);
// カメラのインスタンスを取得する
if ((_camera = SFBCamera::NewInstance()) != null) {
// ダミーのコールバック関数を登録する
error = _camera->RegisterNotify(OnCameraSHP, this);
if (error == SFERR_NO_ERROR) {
// 何か処理を行う
}
// カメラのインスタンスを取得できなかった場合
} else {
error = SFERR_NO_MEMORY;
}
if (error != SFERR_NO_ERROR) {
// エラー処理を行う
}
return error;
}
// コールバック関数
Void Camera::OnCameraSHP(VoidPtr reference, AEECameraNotify* notify)
{
// 実際のコールバック関数を呼び出す
static_cast<CameraPtr>(reference)->OnCamera(notify);
return;
}
// 実際のコールバック関数
Void Camera::OnCamera(AEECameraNotify *notify)
{
switch (notify->nStatus) {
case CAM_STATUS_START: // カメラの起動が完了した
// 何か処理を行う
break;
case CAM_STATUS_FRAME: // 新たなフレームを取得した
// 何か処理を行う
break;
case CAM_STATUS_DONE: // 処理が完了した
// 何か処理を行う
break;
case CAM_STATUS_FAIL: // 処理が失敗した
// 何か処理を行う
break;
case CAM_STATUS_ABORT: // 処理を中止した
// 何か処理を行う
break;
}
return;
}
gzip による Deflate 圧縮データを解凍する
SFXZIPDecoder クラスを利用して、ストレージ クラスや SFBSource 、SFBAStream に格納された gzip による Deflate 圧縮データを解凍します。
// コールバックを使うため、SFXZIPDecoder のインスタンスはクラスのメンバ変数にする
class MyClass {
private:
SFXFile _file; // ファイル クラス のインスタンス
SFXZIPDecoder _decoder; // SFXZIPDecoder クラスのインスタンス
SFXAnsiStringStreamReader _reader; // 読み込み用ストリーム
SFXAnsiString _unzipString; // 解凍後の文字列
public:
Void Start(Void);
// コールバック関数
CALLBACK_DECLARE_SFXANSISTRINGSTREAMREADER(OnFetch)
};
Void MyClass::Start(Void)
{
SFCError error; // エラー
// 読み書きモードでファイルを開く
if ((error = _file.OpenReadOnly(SFXPath("/testdata.tar.gz")))
== SFERR_NO_ERROR) {
// ストレージ ( ファイル ) をデコーダに登録する
if ((error = _decoder.Open(_file)) == SFERR_NO_ERROR) {
// デコーダから読み込み用ストリームを取得する
if ((error = _decoder.GetStreamReader(&_reader))
== SFERR_NO_ERROR) {
// フェッチする
if ((error = _reader.Fetch(CALLBACK_FUNCTION(OnFetch)))
!= SFERR_NO_ERROR) {
// エラーのとき
_reader.Release();
}
}
if (error != SFERR_NO_ERROR) {
// エラーのとき
_decoder.Close();
}
}
if (error != SFERR_NO_ERROR) {
// エラーのとき
_file.Close();
}
}
}
// フェッチが完了したときに呼び出されるコールバック関数
CALLBACK_IMPLEMENT_SFXANSISTRINGSTREAMREADER(MyClass, OnFetch, error)
{
if (error == SFERR_NO_ERROR) {
// エラーが発生していないとき
// 解凍したデータを _unzipString 変数に読み込む
if ((error = _reader.ReadSFXAnsiString(&_unzipString)) == SFERR_NO_ERROR) {
// 文字列を表示する
TRACE("%s", _unzipString.GetCString());
}
}
// 終了処理
_decoder.Close();
_file.Close();
}
ISource インターフェースからデータを読み込む
安全な空きメモリがあるか確認する方法
CheckAvail 関数を使って、安全な空きメモリがあるか確認します。
#define INVALID_MEMORY_SIZE (192000)
Bool MyClass::CheckHeap(Void)
{
SFBHeapSmp heap;
Bool result(false);
// SFBHeap クラスのインスタンスを生成する
if ((heap = SFBHeap::NewInstance()) != null) {
// 指定したサイズのメモリ ブロックが割り当て可能かどうかをチェックする
result = heap->CheckAvail(INVALID_MEMORY_SIZE);
}
return result;
}
SFBHTMLViewer クラスを使った HTML 作成
SFBHTMLViewer クラスは、 IHtmlViewer インターフェースのラッパークラスです。
SFBHTMLViewer クラスを使って HTML データを作成します。
SFBHTMLViewerSmp _html;
HTMLSample::HTMLSample(Void) static_throws
{
// 表示するブラウザーを文字列で入力する
SFXAnsiString data =
"<form>"
"ユーザID :<input type=\"text\" maxlength=\"6\" name=\"id\" value=\"00000\"/><br/>"
"パスワード:<input type=\"text\" maxlength=\"6\" name=\"pass\" value=\"00000\"/><br/>"
"<br/>"
"<center>"
"<input type=\"submit\" value=\"送信\"/><input type=\"reset\" value=\"リセット\"/>"
"</center>"
"</form>"
;
// SFBHTMLViewer クラスのインスタンスを生成する
_html = SFBHTMLViewer::NewInstance();
// 通知コールバックの情報を指定する
_html->SetNotifyFn(OnNotifySCP, this);
// コントロール固有のプロパティまたはフラグを設定する
_html->SetProperties(_html->GetProperties() | HVP_SCROLLBAR);
// コントロールの矩形を設定する
_html->SetRect(SFXGraphics::GetDeviceRectangle());
// ビューワに文字列の内容をロードする
_html->ParseBuffer(data);
}
// 通知コールバック
Void HTMLSample::OnNotifySCP(VoidPtr reference, HViewNotify* info)
{
static_cast<HTMLSamplePtr>(reference)->OnNotify(info);
return;
}
// 通知コールバックの処理
Void HTMLSample::OnNotify(HViewNotify* info)
{
switch (info->code) {
case HVN_DONE: // ロード完了時
break;
case HVN_JUMP: // ユーザー選択リンク時
break;
case HVN_SUBMIT // ユーザーがフォームを送信した時
break;
case HVN_FOCUS: // フォーカス変更時
break;
}
return;
}
MIF ファイルには「ネットワーク」と 「Web アクセス」の特権レベルを設定してください。
C 言語用 BREW API を利用する方法
SophiaFramework プログラムから C 言語用 BREW API を利用する方法は以下のとおりです。
例 1 : IShell インターフェースの場合
SFBShellSmp xshell;
IShellPtr ishell;
// 方法1
if ((xshell = SFBShell::GetInstance()) != null) {
ishell = interface_cast(xshell.Get());
// xshell が有効な間、 ishell を利用できる
// ishell のスコープは xshell のスコープに依存する
}
// 方法2
if ((xshell = SFBShell::GetInstance()) != null) {
ishell = interface_cast(xshell.Detach());
// ishell の解放権限を xshell から取得する
// 開発者が ishell を明示的に解放する
ISHELL_Release(ishell);
}
例 2 : IFileMgr インターフェースの場合
SFBShellSmp shell;
SFBBaseSmp xfilemgr;
IFileMgr* ifilemgr;
// 方法1
if ((shell = SFBShell::GetInstance()) != null) {
// IFileMgr インターフェースを作成する
if ((xfilemgr = shell->CreateInstance(AEECLSID_FILEMGR)) != null) {
// スマートポインタクラスから
// IFileMgr インターフェースへのポインタを取得する
ifilemgr = reinterpret_cast<IFileMgr*>(interface_cast(xfilemgr.Get()));
// IFileMgr インターフェースを利用する
if (IFILEMGR_Test(ifilemgr, "myfile.txt") == SFERR_NO_ERROR) {
// ...
}
// ifilemgr のスコープは xfilemgr のスコープに依存する
// スコープを伸ばすには、xfilemgr と ifilemgr をクラス変数にする
}
}
// 方法2
if ((shell = SFBShell::GetInstance()) != null) {
// IFileMgr インターフェースを作成する
if ((xfilemgr = shell->CreateInstance(AEECLSID_FILEMGR)) != null) {
// スマートポインタクラスから
// IFileMgr インターフェースへのポインタを取得する
ifilemgr = reinterpret_cast<IFileMgr*>(interface_cast(xfilemgr.Detach()));
// IFileMgr インターフェースを利用する
if (IFILEMGR_Test(ifilemgr, "myfile.txt") == SFERR_NO_ERROR) {
// ...
}
IFILEMGR_Release(ifilemgr);
// ifilemgr のスコープは xfilemgr のスコープに依存しないが、
// ifilemgr は開発者が管理する
// IFileMgr インターフェースを利用し終わった時点で
// 開発者が ifilemgr を明示的に解放する
}
}
スマートポインタ型を基底クラスから派生クラスへキャストする