読者です 読者をやめる 読者になる 読者になる

PerlQt移植ヒストリ(第2回)

付属のチュートリアルを使用して、ビルドしたてのPerlQtを早速実行して見た。

$ perl -W -Iblib/arch -Iblib/lib -I$QTDIR/lib -Itutorials-2.0/t1 \
tutorials-2.0/t1/t1
Can't locate object method "new" via package "Qt::Application" (perhaps you 
forgot to load "Qt::Application"?) at tutorials-2.0/t1/t1 line 3.


「ひょっとしたら、"Qt::Application" をロードし忘れた?」と言われても困る。そのようなPMファイルは存在しないのだから。

デバッグコードを挿入して原因を調べたところ、以下の関数に問題があることを発見した。

void pig_autoload_methods(const char *pig0, pig_classinfo *pig1) {
    char *pigmethod;
    if(!_pig_autoloaded_methods)
        _pig_autoloaded_methods = newHV();
    hv_store(_pig_autoloaded_methods,
            (char *)pig0, strlen(pig0), newSViv((IV)pig1), 0);
    pigmethod = new char [strlen(pig0) + 11];
    sprintf(pigmethod, "%s::AUTOLOAD", pig0);
    newXS((char *)pigmethod, (XS((*)))PIG_AUTOLOAD, (char *)__FILE__);
    delete [] pigmethod;
}


この関数は各パッケージのAUTOLOADサブルーチンを定義するものだ。
しかし、肝心のパッケージを作成している処理が見つからない。
これではPerlに「ロードし忘れた?」と言われても仕方が無い。

色々と調べて見たが、パッケージを作成できるC言語の関数は見つからなかった。
そ こで、Perlスクリプトによってパッケージを作成する以下の方法を考えた。

void pig_autoload_methods(const char *pig0, pig_classinfo *pig1) {
    char *pigmethod;
    if(!_pig_autoloaded_methods)
        _pig_autoloaded_methods = newHV();
    hv_store(_pig_autoloaded_methods,
            (char *)pig0, strlen(pig0), newSViv((IV)pig1), 0);
    pigmethod = new char [strlen(pig0) + 11];
#if 0 /* 以下を差し替え */
    sprintf(pigmethod, "%s::AUTOLOAD", pig0);
#else
    sprintf(pigmethod, "%s::autoload", pig0);
    static char def_pkg[] = "\
package %s; \
sub AUTOLOAD \
{ \
    return undef if ($AUTOLOAD eq \"%s\"); \
    &%s; \
} \
1; \
";
    int bytes = sizeof (def_pkg) + strlen(pig0) + strlen(pigmethod) * 2;
    char *pkg = new char [bytes];
    sprintf(pkg, def_pkg, pig0, pigmethod, pigmethod);
    perl_eval_pv(pkg, 1);
    delete [] pkg;
#endif
    newXS((char *)pigmethod, (XS((*)))PIG_AUTOLOAD, (char *)__FILE__);
    delete [] pigmethod;
}


上記の修正により、Perlに「ロードし忘れた?」と言われずに済んだ。
ただし、表示される画面はチュートリアルもサンプルも以下のようにZaurusらしくない。


ここまで来るのに、実際には前回から1週間分の通勤時間と休日の数時間を必要とした。しかし、まだまだ先は長そうだ。

ここで培ったノウハウを以下に記載した。