Perl Hackers Hub

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

この記事を読むのに必要な時間:およそ 2 分

本連載では第一線の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というモジュールですでに実現されています。

注1)
プログラミング言語からCやC++で記述されたライブラリが提供するAPIを呼び出せるようにすることを指します。

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モジュールを作成するために参考になるモジュールやドキュメントを紹介します。

注2)
言語と聞くとまったくの独自言語を想像するかもしれませんが,実際はPerl APIが使えるC言語です。

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.112

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

  • 特集1
    React/Vue.jsで実践!
    コンポーネント設計
    モダンフロントエンドの構造化と分割の新提案
  • 特集2
    RDBMS徹底比較
    PostgreSQL,MySQL,SQL Server,Oracle Database
  • 特集3
    実践Scala
    オブジェクト指向×関数型
  • 一般記事
    自作キーボードのススメ
    デザイン,配列,打鍵感……自由自在

著者プロフィール

上川慶(かみかわけい)

1995年,沖縄生まれPerl育ち。2018年に株式会社メルカリへ新卒入社し,現在はメルカリのマイクロサービスを開発している。大好きな言語はPerlとGoであり,特性としてよく沖縄に帰ることが多い。

学生時代は沖縄のPerlユーザーコミュニティであるOkinawa.pmを運営しており,一応今でも中の人の一人。