Perlテックブログ

ITエンジニアの成長意欲を刺激する技術考察、モジュール開発の日記。Perlイベントや国内や海外のPerlの記事の紹介。

ランタイムと配布時のC/C++バインディングの共通化

Perlでは、C言語バインディングをランタイムにおいて行うInline::Cというモジュールがある。

一方で、モジュールを配布するときには、XSという仕組みを利用する。

もし、これらが同じ方法で行えたとしたら便利だと思わないだろうか。

普段のちょっとした用途で、C/C++バインディングしたいときは、インラインで書いて、CPANモジュールとして配布したい場合は、そのコードがそのまま動く、そういう仕組みだ。

ランタイムと配布時のC/C++バインディングを共通化するためには

必要になると考えているものを、ここで列挙してみる。

サブルーチンがC/C++バインディングであるということを指示する

まず、必要なことは、そのサブルーチンが、C/C++バインディングであるということを指示するということだ。これを支持するために、nativeというキーワードを準備する。nativeキーワード、はPerl6におけるC/C++バインディングのキーワードだけれど、僕はこれをPerl 5に持ってこようとしている。

Perl 5は、後方互換性を維持しながら、新しい機能をモジュールにおいて実現できるように設計されている。

こういう設計方針なので、Perl6でPerl5に必要な機能があれば、持ってくることもできるのだ。そして、僕はnativeというキーワードを持ってきた。

package Math {
  # 三角関数
  native sub acos : double ($x : double);
  native sub asin : double($x : double);
  native sub atan : double ($x : double);
  native sub atan2 : double ($y : double, $x : double);
  native sub cos : double ($x : double);
  native sub sin : double ($x : double);
  native sub tan : double ($x : double);
}

こんな風に、sin関数は、C/C++バインディングなんだよということを、nativeキーワードで教えてあげる。

C言語でsin関数を書く

次は、C言語で、sin関数を書く。

#include <math.h>
#include "spvm_native.h"

double SPVM__Math__sin(SPVM_ENV* env, SPVM_VALUE* args) {
  (void)env;
  
  double value = sin(args[0].dval);
  
  return value;
}

共有ライブラリにコンパイル

これをExtUtils::CBuilderを使って共有ライブラリにコンパイル

配布に含めたい場合は、これを、配布ディレクトリに配置する。

ランタイムで実行したい場合は

ランタイムで実行したい場合は、配布に含めないようにしておいて、実行時にコンパイルして、そのまま読み込むようにする。

SPVMで実現したいことは、現在、配布時とランタイム時で、C/C++バインディング方法が異なるので、これを共通化して簡単に利用できるようにしたいというのがあります。