ブログ

  • Google Documents List Data API アップロード編

    無変換で Google Document にファイルをアップロードするためには, ResumableUploader を使います。 file はファイルへのフルパスになります。

    ClientLoginAuthenticator^ cla = gcnew ClientLoginAuthenticator(
        "App",
        ServiceNames::Documents,
        email,
        password
    );
    ResumableUploader^ ru = gcnew ResumableUploader();
    Document^ entry = gcnew Document();
    entry->Title = "タイトル";
    entry->MediaSource = gcnew MediaFileSource(file, "application/octet-stream");
    Uri^ createUploadUrl = gcnew Uri("https://docs.google.com/feeds/upload/create-session/default/private/full/?convert=false");
    AtomLink^ link = gcnew AtomLink(createUploadUrl->AbsoluteUri);
    link->Rel = ResumableUploader::CreateMediaRelation;
    entry->DocumentEntry->Links->Add(link);
    ru->InsertAsync(cla, entry->DocumentEntry, gcnew Object);
  • Google Documents List Data API ダウンロード編

    ファイルのダウンロードには, DocumentsRequest.Download を使用します。以下のサンプルでは,再度リストを取得しています。これは, Document^ の寿命が分かっていないためです。初めのリスト取得で doc->Id が保存してあり, UI でダウンロード対象が m_id として指定されます。今回のリスト取得で比較を行い,一致した場合はダウンロードします。

    また,ネイティブクラスのメンバにマネージドクラスへのポインタ(この場合, Document^ )を持たせる方法もよく分かっていないため,上記方法をとっています。

    Stream からバッファに一気に読み込む処理がありそうなのですが, .NET がよく分かっていないので1KBずつ読み出しています。

    GDataCredentials^ c = gcnew GDataCredentials(email, pass);
    RequestSettings^ r = gcnew RequestSettings("App", c);
    DocumentsRequest^ dr = gcnew DocumentsRequest(r);
    Feed^ feed = dr->GetEverything();
    for each (Document^ doc in feed->Entries) {
        marshal_context^ context = gcnew marshal_context();
        MYSTR id = context->marshal_as(doc->Id);
        delete context;
        if (id == m_id) {
            Stream^ s = dr->Download(doc, "");
            MYBUF buf;
            array^ bytes = gcnew array(1024);
            pin_ptr p = &bytes[0];
            for (;;) {
                int n = s->Read(bytes, 0, 1024);
                if (n == 0)
                    break;
                buf.Add(n, p);
            }
  • Google Documents List Data API リスト編

    Retrieving a list of documents では, DocumentsService を使用してファイル一覧を取得していますが,後でファイルをダウンロードするときに使う DocumentsRequest.Download に Document を渡す必要があるため, DocumentsRequest を使用してフィードを取得します。

    サンプルソースは以下のようになります。

    GDataCredentials^ c = gcnew GDataCredentials(email, password);
    RequestSettings^ r = gcnew RequestSettings("App", c);
    DocumentsRequest^ dr = gcnew DocumentsRequest(r);
    Feed^ feed = dr->GetEverything();
    for each (Document^ doc in feed->Entries) {
        DocumentEntry^ entry = doc->DocumentEntry;
        entry->Title->Text; // タイトル
        entry->Updated;     // 更新時刻
    }
  • Google Documents List Data API

    Google Documents List Data API が気になってきた。

    C++からだと.NET Client Libraryが呼び出せる模様。(自分はC/C++しか使えないので)。

    まずライブラリをダウンロードする。http://code.google.com/p/google-gdata/downloads/list から Google_Data_API_Setup_1.8.0.0.msi をインストールする。

    以下,呼び側アプリのプロジェクトに移る。

    [全般の共通言語ランタイムサポート]の値を「共通言語ランタイムサポート (/clr)」に設定する。

    Cソースが含まれる場合は,[C/C++]-[詳細設定]-[コンパイル言語の選択]-[C++コードとしてコンパイル(/TP)]に設定する。

    [C/C++]-[全般]-[#using参照の解決]に C:\Program Files\Google\Google Data API SDK\Redist を指定する。

    C++/CLIのコーディングは,http://www.atmarkit.co.jp/fdotnet/special/cppcli/cppcli_03.html が参考になる。

    GData APIの呼び出しは,

    #using <Google.GData.Documents.dll>
    #using <Google.GData.Client.dll>
    #using <Google.GData.Extensions.dll>
    
    using namespace Google;
    using namespace Google::GData;
    using namespace Google::GData::Documents;
    
    DocumentsService ^myService = gcnew DocumentsService("exampleCo-exampleApp-1");
    myService->setUserCredentials("jo@gmail.com", "mypassword");

    このような感じでいけそう。少なくともコンパイルは出来た。Cソース部分でC++としてコンパイルすることからのエラーが出ていて,まだリンクは完了してない。よって動作は未確認。

    リンク完了後,動作確認予定。Google Docsも使用開始しておこう。

  • XSDでCOLLADA

    COLLADAのとっかりはこちら。COLLADA DOMを使った3Dモデルデータの読み込み

    XSDはこちら。CodeSynthesis XSD

    おおまかな流れとしては,

    • XSDをVisual Studioに導入する
    • COLLADA 1.4.1 Schema (includes OpenGL ES Profile)をローカルに保存する。
    • 保存したSchemaをソリューションに追加して,XSDでC++パーサにコンパイルする。
    • コンパイルオプションはこちらにあるように–parts 3等で分割指定が必須。
    • コンパイルしたC++パーサをソリューションに追加する。
    • COLLADAの読み込み部分を作成する。1行で読み込めるが初めから高速化に対応した方がよい。
    • OpenGLの表示処理を作成する。パース結果の利用方法(triangleのみ描画)は下記。
    using namespace COLLADASchema;
    const COLLADA::library_geometries_sequence& g = bhc->m_dae_preview->library_geometries();
    for (COLLADA::library_geometries_const_iterator i = g.begin(); i != g.end(); i++) {
      const library_geometries::geometry_sequence& h = (*i).geometry();
      for (library_geometries::geometry_const_iterator j = h.begin(); j != h.end(); j++) {
        const mesh::triangles_sequence& t = (*j).mesh()->triangles();
        for (mesh::triangles_const_iterator k = t.begin(); k != t.end(); k++) {
          unsigned int numberOfInputs = (*k).input().size();
          unsigned int numberOfTriangles = (*k).p()->size() / numberOfInputs;
          unsigned int offset = 0;
          int texoffset = -255;
          int noroffset = -255;
          for (triangles::input_const_iterator l = (*k).input().begin(); l != (*k).input().end(); l++) {
            if ((*l).semantic() == "VERTEX")
              offset = (*l).offset();
            if ((*l).semantic() == "TEXCOORD")
              texoffset = (*l).offset();
            if ((*l).semantic() == "NORMAL")
              noroffset = (*l).offset();
          }
          for (int ii = 0; ii < numberOfTriangles; ii++) {
            int index = (*k).p()->at(ii * numberOfInputs + offset);
            if (noroffset == -255) {
              glNormal3f(
                (*j).mesh()->source().at(1).float_array()->at(index * 3),
                (*j).mesh()->source().at(1).float_array()->at(index * 3 + 1),
                (*j).mesh()->source().at(1).float_array()->at(index * 3 + 2)
              );
            } else {
              int norindex = (*k).p()->at(ii * numberOfInputs + noroffset);
              glNormal3f(
                (*j).mesh()->source().at(1).float_array()->at(norindex * 3),
                (*j).mesh()->source().at(1).float_array()->at(norindex * 3 + 1),
                (*j).mesh()->source().at(1).float_array()->at(norindex * 3 + 2)
              );
            }
            if (texoffset != -255) {
              int texindex = (*k).p()->at(ii * numberOfInputs + texoffset);
              glTexCoord2f(
                (*j).mesh()->source().at(2).float_array()->at(texindex * 2),
                (*j).mesh()->source().at(2).float_array()->at(texindex * 2 + 1)
              );
            }
            glVertex3f(
              (*j).mesh()->source().at(0).float_array()->at(index * 3),
              (*j).mesh()->source().at(0).float_array()->at(index * 3 + 1),
              (*j).mesh()->source().at(0).float_array()->at(index * 3 + 2)
            );
          }
        }
      }
    }
    

    m_dae_previewは,

    std::auto_ptr<COLLADASchema::COLLADA>   m_dae_preview;
    

    というデータメンバで,COLLADAをロードした結果を保持している。

    COLLADA DOMより少し速度が遅いし,分かりやすさもないので,COLLADAをパースしてみたい人は素直にCOLLADA DOMを使った方がよいかも。

  • MySQLの基本

    開始

    mysql -u ユーザ名 -p

    データベースの一覧

    show databases;

    データベースの選択

    use データベース;

    テーブルの一覧

    show tables;

    あるテーブルの全表示

    select * from テーブル;

    あるテーブルの削除

    drop table テーブル;

    別ファイルのSQL文を流し込む

    mysql --user=ユーザ --database=データベース < ファイル.sql

    レコードを更新する

    update テーブル set hoge='foo' where 条件;

    レコードを削除する

    delete from テーブル where 条件;

    カラムの一覧を表示する

    show columns from テーブル;

    カラムを追加する

    alter table テーブル add カラム名 型;

    カラムを特定カラムの後に追加する

    alter table テーブル add カラム名 型 after 特定カラム;
  • autotools

    aclocal; autoheader; automake -a -c; autoconf
    
  • ODB – C++ Object-Relational Mapping (ORM)

    ODB – C++ Object-Relational Mapping (ORM)

    サーバが落ちたり,再起動したら,世界の時間が巻き戻ってしまうのは困る。メモリ上のオブジェクトをどうハードディスクに保存するか探っていたら,ODBを見つけた。

    gitのリポジトリに追加して,コンパイル。サードパーティのライブラリも全てソースから保持していく。gcc-4.5のpluginを利用しているので,gcc-4.5にアップデート。gcc-4.5-plugin-devパッケージも必要だった。libcutlも必要。libcutlをmake installしているとconfigureがうまくいかず,–with-libcutl=でソースディレクトリを指定してOKだった。

    ODBを作っているCODE SYNTHESISは南アフリカの会社のようだ。XSDなども,COLLADAに対応しているので使ってみようかと思っている。南アフリカの通貨ランドにはたいへんお世話になっているので,親しみを感じる。

    ODB対応のコーディングは下記が肝と分かったが,vectorの中身をname*という感じ(実際にはBHOBJECT*)にしたい。うまくDBに保存できるのだろうか。

    #pragma db value
    class name
    {
    public:
      name (const std::string&, const std::string&);
      ...
    private:
      friend class odb::access;
      name ();
      ...
    };
    
    #pragma db object
    class person
    {
      ...
    private:
      std::vector<name> aliases_;
      ...
    };
    
  • MySQL C API

    MySQL C API

    ユーザー管理はMySQLデータベースでやってみようと思う。いつものようにラッピングクラスを作ったら,MYMYSQLになってしまう。まいまい。

    まずMySQLのデータベース作成を忘れやすい(mediawikiとwordpressの2回のみ作成)のでメモ。

    $ mysql -u root -p
    mysql> CREATE DATABASE dbname;
    mysql> GRANT ALL PRIVILEGES ON dbname.* TO user@localhost
        -> IDENTIFIED BY "password";
    mysql> FLUSH PRIVILEGES;
    mysql> EXIT

    プログラミング・メモ – MySQL の C API を使ってみるを参考にMYMYSQLクラスを作成。テーブルがひとつもないのでmysql_queryがエラー終了。そしてテーブルの作り方も分からない。MySQLというかデータベースのことが何ひとつ分からないので道のりは長い。

    BHACCOUNTSクラスを作成。これはhas-a関係だな,ということでMYMYSQLクラスをメンバーに持たせた。MYMYSQLにCREATE TABLEする関数とINSERT INTOする関数を作って,BHACCOUNTSクラスのLogin関数から呼んで,ログイン処理の骨組みができてきた。XML-RPCとつなげれば,BHクライアントからログイン/ユーザー登録ができるようになる。

    SQLの文法は思ったより難しくなかった。C++から呼び出す際の,もっとジェネリックな仕組みを考えなければならない。現状は,泥臭い文字列操作ばかり。

  • XML-RPC

    Vortex LibraryをラッピングするMYVORTEXSERVERクラスとMYVORTEXCLIENTクラスを作ってみて,うまくサーバークライアント間で通信ができるようになった。しかし依然としてアプリケーションプロトコルのイメージが頭に浮かばない。XMLをやりとりしたら自由度が高そう,と思っていたら,VortexでXML-RPCがサポートされていたので,使ってみようかと思う。IDL/XDLを作ってコンパイルするワンクッションが面倒くさいが,車輪の再発明よりは良いだろう。

    MYVORTEXSERVERにXML-RPCのサポートを追加したら,

    ../../Library/myvortexserver.cpp:119: error: ‘vortex_xml_rpc_accept_negotiation’ was not declared in this scope
    

    とエラー発生。./configureのパラメータ足りなかったかな? と思ってvortexを再ビルドしたが,単に,

    #include <vortex_xml_rpc.h>
    

    が足りないだけだった。libvortex-xml-rpc-1.1.aのリンクも追加。

    MYVORTEXCLIENTもXML-RPC対応(IDL/XDLは使わずRaw API手動呼び出し)したら,

    method_call_free (invocator);
    

    の呼び出しでアボートしたので削除。無事動作。

    IDL/XDLのコンパイル出力はCになるようなので,アップデート後にいちいちC++に書き換えるのが面倒だ。なので,このままRaw API使用で突っ走るかも。

    さらにBHPROTOCOLSERVERとBHPROTOCOLCLIENTでラッピングして,BHPROTOCOLの実装準備完了。BHPROTOCOLからVortexを呼んでいるところは直すこと。抽象化。疎結合。