Perl Hackers Hub

第53回Cを用いたPerl拡張入門―Inline::Cで体験してみよう!(1)

本連載では第一線のPerlハッカーが回替わりで執筆していきます。今回のハッカーは上川慶さんで、テーマは「Cを用いたPerl拡張入門」です。

本稿のサンプルコードは、本誌「WEB+DB PRESS Vol.108」サポートサイトから入手できます。

Cを用いたPerl拡張入門

筆者たちPerl Mongerは先人たちが築き上げてきたモジュールを使いながらPerl製のプログラムを作成します。しかしながら、すべてのモジュールがPerlだけで作成されているわけではありません。中にはCの力を借りてPerlの拡張を行っているものもあります。

Cを用いてPerlを拡張する理由

ではなぜ、Cを用いてPerlを拡張する必要があるのでしょうか。それには次の点が挙げられるでしょう。

ホットスポットの改善

ホットスポットとは、処理の中でとても時間がかかっている部分を指します。みなさんが今までにPerlで記述した処理の中には、Perlゆえにパフォーマンスが落ちた処理があるはずです。そのような箇所をCで書きなおすことで、パフォーマンスを改善できます。

Perlゆえにパフォーマンスが落ちる処理について、詳しくは後述します。

ライブラリとのCバインディング

たとえばある画像をPerlから簡単かつ高速に処理したい場合、ImageMagickとCバインディング[1]を行うことで、ImageMagickの機能をPerlのコードとして表現できます。このCバインディングは、Image::Magickというモジュールですでに実現されています。

Cを用いてPerlを拡張する方法

Cを用いてPerlを拡張する方法は2つあります。一つは、PerlのAPIをCのマクロでラップしたXSという言語[2]を用いる方法です。もう一つは、Inline::Cモジュールを用いてPerlコード内に直接Cの関数を記述する方法です。

XSはCで作成した関数をPerlから呼び出すインタフェースとしての役割を持ちます。主にXSモジュールを作成するために用いられ、.xsファイルへ記述します。記述したCの関数をPerlで呼び出すために、XSLoaderというモジュールを.pmファイル内で利用してCの関数をロードします。

Inline::CはPerlでCを記述するために利用されるモジュールです。そのためXSとは対照的にモジュール化を必要とせず、CのコードをPerlのソースコード上に記述できます。Inline::Cは主に実行するスクリプトやアプリケーションに記述して使用します。

本稿ではXSモジュールを作成するための準備として、PerlとCが連携できるようなコードの書き方を学んでいきます。コードの書き方を集中して学ぶために、XSモジュールの作成はせずに、簡単に編集や実行結果の確認が行えるよう、Inline::CをPerlのスクリプト上で用います。また、本稿の最後に次のステップとして、XSモジュールを作成するために参考になるモジュールやドキュメントを紹介します。

Perlの内部で扱われる型の世界

Cで拡張するために避けて通れないのが型の世界です。なぜなら、CはPerlと違って型を厳密に扱う言語だからです。また、PerlはCで開発されているため、Perl上で表現される値すべてに内部では型が定義されています。

たとえばPerl上でよく表現されるデータタイプとしてスカラがあります。スカラは次のように表現されるものです。

my $i = 10;
my $s = "Hello, World";

Perlの内部でスカラは、1つの値を格納するSVScalar Value型として定義されています。

必要最小限の基本型を理解する

Cを用いてPerlを拡張するために最小限に理解しておいたほうがよい型が、先ほどのSVです。Perlの内部で定義されている型は、すべてSVと関係を持ちます。たとえば配列を表すAVArray Valueや連想配列を表すHVHash Valueは、SVから派生した(is-a関係を持つ)型です。そのため、AV、HVからSVに変換できます。

また、SVは内部にプリミティブな型も保持(has-a関係を持つ)しています。そのプリミティブな型を紹介していきます。

IV─⁠─符号付き整数の型

IVInteger Valueは、整数を表す型です。Cのint型へキャストできます。

my $iv = 10;
my $iv2 = -10;

UV─⁠─符号なし整数の型

UVUnsigned Integer Valueは、符号なしの整数を表す型です。Cのunsigned int型へキャストできます。

my $uv = 1;

NV─⁠─倍精度の型

NVNumeric Valueは、倍精度を表す型です。Cのdouble型へキャストできます。

my $nv = 3.333;

PV─⁠─文字列の型

PVPointer Valueは、文字列を表す型です。Cのchar*型へキャストできます。

my $pv = "Hello, World";

SVとプリミティブな値

SVからプリミティブな値を取得するには、次のAPIを用います。

/* SV* sv = ...; */
IV iv = SvIV(sv);
UV uv = SvUV(sv);
NV nv = SvNV(sv);
PV pv = SvPV_nolen(sv);

プリミティブな値を表すSVを作成したい場合は、次のAPIを用いて変換します。

SV* sviv = newSViv(12);
SV* svuv = newSVuv(3);
SV* svnv = newSVnv(3.14);
SV* svpv = newSVpv("hello", 0);

これらの操作を覚えておくことで、SVからCのintやchar*の作成も容易になります。

<続きの(2)こちら。>

WEB+DB PRESS

本誌最新号をチェック!
WEB+DB PRESS Vol.130

2022年8月24日発売
B5判/168ページ
定価1,628円
(本体1,480円+税10%)
ISBN978-4-297-13000-8

  • 特集1
    イミュータブルデータモデルで始める
    実践データモデリング

    業務の複雑さをシンプルに表現!
  • 特集2
    いまはじめるFlutter
    iOS/Android両対応アプリを開発してみよう
  • 特集3
    作って学ぶWeb3
    ブロックチェーン、スマートコントラクト、NFT

おすすめ記事

記事・ニュース一覧