ブログトップ 記事一覧 ログイン 無料ブログ開設

サンプルコードによるPerl入門 〜 安定と信頼のPerlを学ぼう 〜

3000-01-01

サンプルコードによるPerl入門 - 目次

 サンプルコードを中心としたPerlの入門サイトです。 Perlを使ったWebサイトの作り方も解説しています。関数やモジュールなPerlの便利な機能の解説も行っています。(スマートフォン、タブレットの場合のPCサイト表示はこちらから行うことができます)

Perl基礎 - Perlの基礎を覚えよう

 Perlの基礎について解説します。Perlのインストール、基本的な構文、配列、ハッシュ、正規表現、ファイル入出力、オブジェクト指向などを学ぶことができます。


  1. コマンドプロンプト- コマンドプロンプトの使い方
  2. Perlとは - Perlの特徴について
  3. Perlインストール - Perlのインストール方法
  4. Perl基礎文法最速マスター - Perlの基礎をすばやく学習
  5. 現代的なPerlの記述方法 - Perlの現代的な書き方
  6. 実践で役立つPerl正規表現 - Perlの正規表現で頻繁に利用するテクニック
  7. 配列とハッシュを自由に扱う - ハッシュと配列の扱い
  8. サブルーチンの作成 - サブルーチンの作成方法
  9. Perlのスコープを理解する - スコープという概念を学習
  10. ファイル入出力の基礎 - ファイルの読み書き
  11. Perlオブジェクト指向入門 - オブジェクト指向の入門
  12. デバッガの手引き - デバッガの紹介
  13. Perl豆知識 - 知っておくと便利な豆知識
  14. Perl FAQ - Perlでよくある質問に答える

Mojolicious入門 - PerlでWebサイトを作ろう

 Mojolicious入門 〜 PerlでWebサイトを作ろう 〜
Perlを学ぶ楽しい方法のひとつはWebサイトを作成してみることです。Webサイトを作成できれば、インターネット上で自分でサービスを公開することもできます。

 MojoliciousはPerlでWebサイトを作る場合の代表的なフレームワークです。Mojoliciousを使えば、簡単にWebサイトを作成することができます。Ruby on Railsを知っている方は、これのPerl番だと考えていただけると想像しやすいと思います。

Perl書籍

 Perl関連の書籍の紹介です。「サンプルコードによるPerl入門基礎編」「簡単プログラミング Perl/CGI」と「もっと自在にサーバを使い倒す 業務に役立つPerl」は僕が書いています。

Perl応用

 基礎を学び終えたら、関数とモジュールについて知るのが、上達の近道です。よく使用する関数や、モジュールについて解説しています。またデータベース操作についても学ぶことができます。

  1. よく使用する関数一覧 - よく使用する関数の紹介
  2. Perlモジュール徹底解説 - モジュールについての詳しい解説
  3. Validator::Customリファレンス - HTMLフォームのバリデーション
  4. SQLiteで学ぶデータベース操作の基礎 - SQLiteとDBIを使ったデータベース操作
  5. DBIx::Customリファレンス - データベースに便利にアクセス
  6. PDLによる統計解析 - PDLモジュールを使った統計解析
  7. PerlプログラマのためのC言語入門 - PerlプログラマのためのC言語の解説です
  8. XSによるC/C++バインディング入門 - PerlからC言語あるいはC++で書かれた関数を呼び出します
  9. Perlその他の情報

Perlリファレンス

Perl逆引き辞典

 逆引き辞典です。やりたいことをさがせます。簡単なサンプルつきです。

コメントデバッグコマンドライン引数配列
ハッシュサブルーチンモジュール数値演算
ビット演算文字列文字コード正規表現
ファイルとディレクトリファイルとディレクトリ(UNIX系OS)ファイル入出力制御構造
変数情報取得日付と時刻開発環境構築
特殊変数プラグマワンライナーPerlとMySQLの連携
自動試験プロセス間通信ソケットオブジェクト指向

Perlその他

CentOS・Red Hat Linux実践テクニック

Perl以外の技術情報

2015-01-13

モジュール紹介「App::RemoteCommand リリース」

 並列にSSHにコマンドを実行するコマンドのようだ。

App::RemoteCommand リリース

 特徴は以下のとおり。

特徴

App::RemoteCommand およびそのフロントエンド rcommand の特徴は

複数ホストに並列にコマンドを実行できる。

複数ホストをいい感じに指定できる。

sudo password を最初に覚えておいて、以後自動で補完してくれる。

ローカルにあるスクリプトを直接指定できる。

コマンド出力に実行したホスト名、時刻をつけてくれる。

最後にどのホストで成功したか、失敗したかのサマリーがでる。

使い方

 複数ホストがあって、同時に同じことを何かしたいときに便利そう。


ニュース

 

2015-01-12

オブジェクト指向関連のAPI | XSによるC/C++バインディング入門

 オブジェクト指向に関連したXSのAPIを紹介します。

あるクラスを継承しているかどうかを確認する

 sv_derived_from関数を使用します。指定したクラスを継承している場合は、真が返ってきます。

sv_derived_from(sv_obj, "MyClass");

 この関数は、配列のリファレンスであることや、ハッシュのリファレンスであることを確認するのに利用することも可能です。

/* 配列のリファレンス */
sv_derived_from(sv_obj, "ARRAY");

/* ハッシュのリファレンス */
sv_derived_from(sv_obj, "HASH");


XSによるC/C++バインディング入門

2015-01-10

おじいさんのPerlよもやま話 - 動的配列

f:id:perlcodesample:20150110115737j:image:medium

「おじいさん、何かPerlの話して」

f:id:perlcodesample:20150110115736j:image:medium

「そうじゃなぁ、ぼんちゃんは、勉強熱心じゃなぁ。そうじゃ、動的配列の話はどうじゃろうか。」

f:id:perlcodesample:20150110115737j:image:medium

「うん、配列という言葉は聞いたことがあるけれど、動的配列って言葉はじめてきいたよ。なにそれ。」

f:id:perlcodesample:20150110115736j:image:medium

「それじゃあ、まず最初に配列というものがどういうものか確認しておきたいよ。ぼんちゃん、説明できるかな」

f:id:perlcodesample:20150110115737j:image:medium

「配列というのは、複数の値を入れることができる箱のようなものだと思う。C言語だとこう書くんだよ。僕、これは学校で習ったんだ。1,2,3という値を保存しておくことができるよ。」

int nums[3] = {1, 2, 3};

f:id:perlcodesample:20150110115736j:image:medium

「すごいな、ぼんちゃん。配列を理解しているね。この配列は1,2,3という値を保存しているね。じゃあ、もし4という値を追加したい場合どうじゃろか。できるかな。」

f:id:perlcodesample:20150110115737j:image:medium

「こうかな。あれ、でも、なんかエラーになるね。3つしか入らなにのに、はみ出しているからかな。わかんない。おじいさん、教えて。」

int nums[3] = {1, 2, 3};
nums[3] = 4;

f:id:perlcodesample:20150110115736j:image:medium

「そうじゃよ。はみ出しているからエラーになっているんじゃよ。こういう代入することのできる数が決まっている配列を静的配列というんじゃ。ぼんちゃんが習った配列は、静的配列というものなんじゃよ。でも、自由に値を追加できたらいいと思わないかい。」

f:id:perlcodesample:20150110115737j:image:medium

「うん、自由に値が追加できたら便利だよね。」

f:id:perlcodesample:20150110115736j:image:medium

「そうじゃろ、そうじゃろ。自由に値が追加できる配列のことを、動的配列というんじゃ。これがPerlの便利なところで、なんと、Perlでは、デフォルトの配列の実装が動的配列なんじゃよ。これは、配列革命といってもよいんじゃ。ライブラリではなくって、言語機能として、動的配列を、配列として採用したんじゃよ。

f:id:perlcodesample:20150110115737j:image:medium

「おじいちゃん、なんか興奮してるね。」

f:id:perlcodesample:20150110115736j:image:medium

「ふぉふぉふぉ、熱くなってしまったのぉ。Perlでは、こんな感じで書いてもエラーにならないんじゃよ。」

my @nums = (1, 2, 3);
$nums[3] = 4;

f:id:perlcodesample:20150110115737j:image:medium

「便利だね。おじいちゃん、今日は動的配列について教えてくれて、ありがとう。」

f:id:perlcodesample:20150110115736j:image:medium

「それはよかった。ぼんちゃん、プログラミングは、こつこつ毎日が上達のこつじゃよ。がんばっての。」

イラストはみふねたかしさんいらすとんからの提供です。

2014-12-20

Perl XSメモリ管理完全マニュアル

 XSのメモリ管理に関するマニュアルです。

Perlのメモリ管理はリファレンスカウント方式

 まず基礎知識としてPerlのメモリ管理は、リファレンスカウント方式によって、行われているということを、知っておいてください。リファレンスカウント方式では、リファレンスカウントが0になった時点で、メモリの解放が行われます。つまり、Perlにおいてメモリ解放を行うということは、リファレンスカウントを0にするという操作を行うことと等しいです。

 リファレンスカウント方式についてもう少し説明しておきます。Perlの変数においては、最初に変数を宣言したときに、その変数のリファレンスカウントは1になります。また、変数への参照が作られると、リファレンスカウントが1増やされます。

{
  # $strのリファレンスカウントは1になる。
  my $str = 'Hello';
  
  # $strのリファレンスカウントは2になる。$str_refのリファレンスカウントは1になる
  my $str_ref = \$str;
}

 またPerlではスコープを抜けると、自動的に変数が解放されます。これは、なぜかというと、変数は、自動的に、モータルと呼ばれる状態になっているからです。モータルという概念は非常に重要です。モータルとは、「スコープを抜けたときに、リファレンスカウントが自動的に1減らされる状態」という意味です。

 上記のコードでスコープから抜けたときに何が起こるかを記述します。

{
  # $strのリファレンスカウントは1になる。
  my $str = 'Hello';
  
  # $strのリファレンスカウントは2になる。$str_refのリファレンスカウントは1になる
  my $str_ref = \$str;
}
# $str_refのリファレンスカウントが1減らされて0になります。
# $str_refのリファレンスカウントが0になったので、$str_refは解放されます。
# $str_refが解放されたので、$strのリファレンスカウントは2から1になっています。
# $strのリファレンスカウントが1減らされて0になります。
# $strのリファレンスカウント0になったので、$strは解放されます。
# ('Hello'は$strの内部に含まれているのこれも解放されます)

 このような経緯をたどって、メモリは解放されます。

XSにおけるメモリ管理の基礎

 次にこれを踏まえてXSにおけるメモリ管理の基礎について解説します。

Perlの変数

 最初にPerlの変数について簡単に解説します。

 Perlの変数について解説しておきます。まず内部的には、スカラ変数は「SV*型」で表現されます。配列は「AV*型」、ハッシュは「HV*型」で表現されます。まずこのみっつを覚えましょう。リファレンスはもちろん「SV*型」に代入できます。そして、内部的には、「AV*型」と「HV*型」は、「SV*型」から派生しているということを、覚えておきましょう。これは、アップキャスト、ダウンキャストができるという意味です。

 スカラ変数の作成は次の関数で行います。XSにおいては、文字列、浮動小数点、整数で、作成する関数が異なるということを覚えておきましょう。

SV* sv_str = newSvPV("Hello", 0);
SV* sv_num = newSvNV(1.2);
SV* sv_num_int = newSvIV(4);

 配列とハッシュの生成は次の関数で行います。

AV* av_nums = newAV();
HV* hv_scores = newHV();

 リファレンスの生成は次の関数で行います。

SV* sv_str_ref = newRV_inc(sv_str);

 他のnewRVという関数もありますが、リファレンスを生成するときは、newRV_incで、リファレンスカウントを1増やすことが原則です。

作成した変数はすべてモータルにする

 次にメモリ管理に進みます。Perlのメモリ管理の鉄則は、新しく作成するPerlの変数は、すべてモータルにするということです。モータルにすることによって、スコープを抜けた変数のリファレンスカウントは1減らされ、自動的にメモリ解放されます。

新しく作成するPerlの変数はすべてモータルにする。

 モータルにするにはsv_2mortal関数を使用します。引数には「SV*型」を受け取り、戻り値はモータルにされた「SV*型」です。

sv_2mortal(SV* sv_var)

 次のように使用します。

SV* sv_str = sv_2mortal(newSvPV("Hello", 0));

 sv_2mortalに「AV*型」「HV*型」などを渡すには、「SV*型」にアップキャストして、さらに受け取るときに「AV*型」「HV*型」にダウンキャストする必要があります。

AV* sv_nums = (AV*)sv_2mortal((SV*)newAV());
HV* hv_nums = (AV*)sv_2mortal((SV*)newHV());

 リファレンスを作成する場合もsv_2mortalを使います。

SV* sv_str_ref = sv_2mortal(newRV_inc(sv_str));

 このように変数をモータルにしておくと、Perlのスコープが終わった時点で、リファレンスカウントが1減らされ自動的に解放されます。C言語のスコープではなくってPerlのスコープが終わった時点なので、区別しましょう。以下のようなXSの関数は、内部的には、関数全体がPerlのスコープで囲われています。

SV*
foo(...)
  PPCODE:
{
  /* Perlのスコープの開始 */
  
  SV* sv_str = sv_2mortal(newSvPV("Hello", 0));
  
  XSRETURN(0);
  
  /* Perlのスコープの終わり */
}

 以下のように戻り値として返したときは、Perlのコードに戻った時点で、リファレンスカウントが1増やされ、モータルになっているのでリファレンスカウントが1減らされるので、結果としてリファレンスカウントは変化しません。

SV*
foo(...)
  PPCODE:
{
  /* Perlのスコープの開始 */
  
  SV* sv_str = sv_2mortal(newSvPV("Hello", 0));
  
  /* スタックに積んで、戻り値として返却 */
  XPUSHs(sv_str);
  XSRETURN(1);
  
  /* Perlのスコープの終わり */
}

配列とハッシュにデータを格納する場合

 上記の鉄則を守りながらコーディングをしていくと、配列とハッシュにデータを格納した場合にメモリ解放がうまくいきません。なぜなら、配列とハッシュは、それ自体が破棄されるときに、内部に含まれる「SV*型」のデータのリファレンスカウントを1下げてしまうためです。

 これを回避するために、配列とハッシュにデータを格納する場合は、リファレンスカウントを手動で1増やしてあげる必要があります。配列の場合は、av_push,av_storeを使う場合、ハッシュの場合はhv_storeを使う場合がこれに該当します。リファレンスカウントを増やすにはSvREFCNT_inc関数を使用します。

/* 配列に格納する場合 */
SV* sv_num = sv_2mortal(newSvIV(3));
AV* av_nums = (AV*)sv_2mortal((SV*)newAV());
av_push(av_nums, SvREFCNT_inc(sv_num));

/* ハッシュに格納する場合 */
SV* sv_score_math = sv_2mortal(newSViv(60));
HV* hv_scores = (HV*)sv_2mortal((SV*)newHV());
hv_store(hv_scores, "math", strlen("math"), SvREFCNT_inc(sv_score_math), 0);

Cの構造体に、Perlのデータを格納する場合

 Cの構造体にPerlのデータを格納する場合は、自分でメモリ管理を行う必要があります。この話の前提として、C言語の構造体をPerlのオブジェクトとして扱う方法を見ていただくとよいと思います。

 C言語の構造体に、「SV*型」を保存したい場合を考えましょう。sv_nameというメンバを持つPeopleという構造体を宣言してみました。

struct People {
 SV* sv_name;
};

 この場合は、代入するときにリファレンスカウントをSvREFCNT_incを使って増やします。そうしなければ、Perlのスコープを抜けた瞬間にリファレンスカウントは1下げられ、勝手に解放されてしまうからです。

SV*
foo(...)
  PPCODE:
{
  /* 省略 */
  
  /* 構造体の作成(ポインタとして作成) */
  People* people = (People*)malloc(sizeof(People));
  SV* sv_name = sv_2mortal(newSvPV("kimoto", 0));
  people->name = SvREFCNT_inc(sv_name);
  
  /* 省略 */
}

 そして、デストラクタの中で、リファレンスカウントをSvREFCNT_decを使ってひとつ下げます。

void
DESTORY(...)
  PPCODE:
{
  // オブジェクトを取得
  SV* people_obj = ST(0);
  
  // デリファレンス
  SV* people_sv = SvROK(people_obj) ? SvRV(people_obj) : people_obj;
  
  // SV*型をsize_t型に変換
  size_t people_iv = SvIV(people_sv);
  
  // size_t型をポインタに変換
  People* people = INT2PTR(People*, people_iv);
  
  // sv_nameを解放
  SvREFCNT_dec(people->sv_name);
  
  // People*を解放
  free(people);
  
  XSRETURN(0);
}

 このようにC言語の世界の構造体(クラスも同じ)のメンバにデータを保存したい場合は、手動でリファレンスカウントの増加と減少を行う必要があります。

まとめ

 まとめると、要点は3つ。

  1. 新しくPerlの変数を作成した場合はsv_2mortalを使って変数をモータルな状態にする。
  2. 配列とハッシュに値を格納するときは、SvREFCNT_incを使って手動でリファレンスカウントを増やす。
  3. 構造体のメンバに保存する場合は、格納するときにSvREFCNT_incでリファレンスカウントを増やし、デストラクタで、SvREFCNT_decを使って、リファレンスカウントを1減らす。

 これで、たいていの場合には対処できると思います。


XSによるC/C++バインディング入門