gcc でコンパイルできるコードを Visual C++ でコンパイルすると namespace 辺りでエラー。 うーんうーん。 半時間以上たって、判明したのはソース中の日本語 EUCによる問題。 Linux で書いていたコードをとりあえず持ってきて make していたので...
泣き。
投げ。とりあえず nmake 用 Makefile を書いてお茶をにごす。
以前チェックしていたフリーの C++ 暗号化クラスライブラリ。 gzip や zlib 圧縮もサポート。 MSVC 6.0 でも OK。 ちょっと、使って見ようかなと。
使い方は、Read denis bider の User Guide がよさそげ。
PDLを使ったPerl数値処理プログラムによりインタラクティブ性が求められるようになってきたので、一部をCで書いて高速化する事を検討。 問題は Linux でも Windows + ActivePerl でもすんなり動くかどうか。
とりあず PDL::PP のサンプルから sumit 関数あたりを MathEx.pd に書いておく。
Foo::Bar パッケージの中の Foo::Bar::Math の一部を Foo::Bar::MathEx に移して、C extension 化したい。 ということで lib/Foo/Bar/MathEx.pd として、Makefile.PL の各種設定をしてみる。
がどうもうまくいかない。 PDL::PP の Makefile.PLサポートは、Makefile.PL と同じ位置に .pd がある事を想定しているようなので、いろいろと小細工をしなければならない。 一方 Perl の XS は Foo::Bar のベース名から Bar.so を作る前提になっているようで、これまたパッケージの中の一部のモジュールをどうもXS化しにくい。
Perl の ext/SDBM_File を真似て、子 Makefile.PL を使ってみることにした。
Foo-Bar-x.xx | +- Makefile.PL | +- lib | | | +- Foo | | | +- Bar.pm | | | +- Bar | | | +- Math.pm | | | +- MathNoEx.pm | | | ... | | +- blib/... | +- MathEx | | | +- Makefile.PL | | | +- MathEx.pd ...
パッケージディレクトリの下に MathEx ディレクトリを作り、そこに Makefile.PL と MathEx.pd を置く。 Makefile.PL は MathEx.pd 専用になるので、PDL::PP の標準的なものでOKになる。
全体のパッケージング・PPM化・インストール等が面倒にならないかと心配したが、Foo-Bar パッケージ化で perl Makefile.PL、make xxx を実行すれば子Makefile.PLまできちんと面倒をみてくれる。 MathEx 以下でビルドしたものもパッケージの blib に一緒に入れてくれるし(=一緒にインストールできる・PPM化できる)。 逆に make dist の際には子Makefileの方は余計なとりまとめはしないで、親Makefileが一括して tar.gz に入れてくれる。 これはよい。 MathEx.pd もきちんと Foo/Bar/MathEx.so になった。
XSが使えない環境のために、PerlとPPの両方で関数を書いておく。 XSが使えれば MathEx を、使えなければ MathNoEx.pm を使うように。 表向きのAPIは Foo::Bar::Math とし、ここで AUTOLOAD を使ってどちらか一方を呼び出すようにする。 間接呼び出しにして遅くなるのはいやなので、シンボルテーブルを直接設定する。
use vars qw($IMPLEMENT_CLASS $AUTOLOAD); BEGIN { $IMPLEMENT_CLASS = 'Foo::Bar::MathEx'; eval "use $IMPLEMENT_CLASS"; if ($@) { warn "Can't load $IMPLEMENT_CLASS: $@"; $IMPLEMENT_CLASS = 'Foo::Bar::MathNoEx'; eval "use $IMPLEMENT_CLASS"; die $@ if $@; } } sub AUTOLOAD { my $name = $AUTOLOAD; $name =~ s/.*://; my $implement = $IMPLEMENT_CLASS . '::' .$name; no strict "refs"; *{$name} = \&{$implement}; # ここでシンボルテーブル設定 return &{$implement}(@_); }
最初は、AUTOLOAD の最後の行で die したら、trap してエラーメッセージ中のパッケージ名(Foo::Bar::MathEx や Foo::Bar::MathNoEx)を呼び出された Foo::Bar::Math に置換して die し直すようにしようかと思ったが面倒なのでやめ。
使っているWindows BOX には Visual C++ 6 が入っているので、XSも問題なくビルドでき PDL extension もうまく動いた。
PPM化までここで済ませば、他のPCにも持っていけるはず。
これでバシバシPPで書けるわけだが、PPがこれまた難解で最初は苦労しそう。
Wx::ActiveX の Perl 5.6.1 用バイナリ(PPM パッケージ)が配布されていないのでビルドする。 最初はPPM パッケージ化された wxPerl (Wx-0.19-wxmsw2.4.2-win32-u-5.6.1.zip) と wxWidgets 2.4.2 で作成しようと思ったが、うまくいかないので全部ビルドすることに。
wxMSW-2.4.2-setup.zip を C:\usr\local\wxWindows-2.4.2 へ。
ドキュメントの通り、wxWidgets をビルド後、モジュールを作成。 コンパイルには Visual C++ 6 を使用。
set WXWIN=C:\usr\local\wxWindows-2.4.2 set WXDIR=C:\usr\local\wxWindows-2.4.2 cd %WXDIR%\src\msw nmake -f makefile.vc FINAL=1 dll cd %WXDIR%\contrib\src\stc nmake -f makefile.vc FINAL=1 WXUSINGDLL=1 cd %WXDIR%\contrib\src\xrc nmake -f makefile.vc FINAL=1 WXUSINGDLL=1
Wx-0.20.tar.gz を展開したディレクトリに移動し(WXWIN, WXDIR は前記と同じように設定したまま)、
perl Makefile.PL nmake nmake test make_ppm
で PPM パッケージ化まで。
先に wxPerl をインストールしておいてから、
set WXWIN=C:\usr\local\wxWindows-2.4.2 set WXDIR=C:\usr\local\wxWindows-2.4.2 perl Makefile.PL nmake nmake test make_ppm
で PPM パッケージ化。インストール。
demo ディレクトリにあるサンプルで、IE、Flash Player、Acrobat、Windows Media Player を貼りつけられていることを確認。
Visual C++ 2005 で開発のプログラムがどうもメモリリークしているっぽい。 メモリリーク検出を仕込む方法のメモ。
デバッグバージョンのヒープ割り当て関数を使うようにするマクロ定義と crtdbg.h のインクルードをする。 メモリリーク情報ダンプの際にレポートにファイル名と行番号が出るように new を書き換えるマクロを定義する。
// デバッグバージョンのヒープ割り当て関数を使うようにする。 #ifdef _DEBUG #define _CRTDBG_MAP_ALLOC #include <stdlib.h> #include <crtdbg.h> #endif // _CRTDBG_MAP_ALLOC に関係なくプリコンパイルしたいもの。 // かつ new を書き換えるとコンパイルが通らなくなるヘッダファイル群。 #include <string> #ifdef _DEBUG // プリコンパイルするほどではないけど、 // new を書き換えるとコンパイルが通らなくなるヘッダファイル群。 // 例えば。 #include <map> #define new new(_NORMAL_BLOCK, __FILE__, __LINE__) #endif // プリコンパイルしていもの。 #include <myproj/utility.h>
終了時にメモリリーク情報をダンプさせるようにする。 また、コンソールアプリケーションの標準エラー出力にレポートが出力されるように設定する。
int main(int argc, char* argv[]) { // 終了時にメモリリーク情報をダンプさせる。 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); // レポートをファイルに書き出させる。 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); // レポートを標準エラー出力に出力させる。 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); // 処理を開始。 ... }
Naney (なにい)です。株式会社ミクシィで SNS 事業の部長をしています。
nDiki は1999年1月に始めたコンピュータ日誌を前身とする Naney の Web 日記(兼パーソナルナレッジベース)です。
#nNote タグがついている記事は他の記事に比べて、より断片的・未整理・不完全なちょっとしたノートです。まだ結論に至っていない考えなども含まれます。頻繁/大幅に更新したり削除したりすることがあります。
ナレッジベースアプリケーション Obsidian で書いているノートの一部を notes.naney.org で 公開しています。
※内容は個人的見解であり所属組織とは関係ありません。