ホーム > デベロッパ > SophiaFramework > BREW C++ 逆引きコード集

BREW C++ プログラミング 逆引きコード集 : インターフェイス・ラッパー

C++ で作成されたBREW アプリで、BREW インターフェイス (BREW API) を使う方法です。
SophiaFramework を用いています。

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 クラスを利用して、ストレージ クラスや SFBSourceSFBAStream に格納された 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 インターフェースからデータを読み込む

SFXSource クラスを利用して、ISource インターフェースからデータを読み込みます。

SFXSource source; 
static ACharConst data[] = "test data"; // 読み込むデータ
SFXAnsiString string;           // 書き込むデータ
SFXBinaryStreamReader reader;   // メモリ読み込み用ストリーム
SFBSourceUtilSmp util;
SFBSourceSmp bs;

// メモリブロックから SFBSource を作成する
util = SFBSourceUtil::NewInstance();
util->SourceFromMemory(data, sizeof(data), null, null, &bs);

// ストレージを開く
if (source.Open(bs) == SFERR_NO_ERROR) {

    // メモリ読み込み用ストリームを取得する
     if (source.GetStreamReader(1024, &reader) == SFERR_NO_ERROR) {

        reader.Fetch();  // フェッチする ( データを読み込む ) 
        reader >> string; // ストリームにデータを読み込む

        // 文字数を取得する size = 9
        TRACE("size = %d", string.GetLength());   
        // 内部バッファを取得する read = test data   
        TRACE("read = %s", string.GetCString());  

        reader.Release();  // ストリームを解放する
    }
    source.Close();  // メモリ ストレージを閉じる
}
      

安全な空きメモリがあるか確認する方法

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 を明示的に解放する
   }
}
      

スマートポインタ型を基底クラスから派生クラスへキャストする

スマートポインタ型のポインタを基底クラスから派生クラスへキャストするには、
static_pointer_cast<>() 関数を使用します。
スマートポインタ型のポインタは、static_cast<>() でキャストしてはいけません。

SFBBaseSmp base;
SFBGraphicsSmp graphics;

base = SFBGraphics::NewInstance();
graphics = static_pointer_cast<SFBGraphics>(base);

この他にも、reinterpret_pointer_cast, const_pointer_cast,
dynamic_pointer_cast が利用できます。

参照 SFBGraphics::NewInstance