3

私は現在、最初の XS モジュール (C math-library の単なるラッパー) を作成しており、まあまあの成功を収めています。最大の問題は、ドキュメントが非常に理解しにくい、または不完全であることです。

XS でコンストラクターを作成し、ライブラリーからいくつかの関数をメソッド呼び出しとして実装することに成功しました。それはうまくいきます。

今度は、手続き型インターフェイスも実装したいと考えています。このため、メソッド呼び出しかどうかを知る必要があります。メソッド呼び出しの場合は、関数で計算する数値がインスタンスに格納されます。関数の手続き呼び出しの場合は、最初の引数として指定された数値です。これは、コサイン関数の現在のコードです。

double
cos(...)
    CODE:
        SV *arg = newSVsv(ST(0));
        if (sv_isobject(arg)) {
            HV *self_hv = MUTABLE_HV(SvRV(arg));
            SV **callback_ptr = hv_fetchs(self_hv, "Number", 0);
            SV *zahl = *callback_ptr;
        }
        else {
            SV *zahl = newSVnv(arg);
        }

        double x = SvNV(zahl);
        RETVAL = cos(x);
    OUTPUT:
        RETVAL
4

2 に答える 2

5

一般的に言えば、メソッドまたは関数のいずれかとして呼び出されることを意図したサブルーチンを作成することは、悪い考えです。これを行う有名なモジュールが 1 つまたは 2 つありますが (CGI.pm が思い浮かびます)、ほとんどの場合、これはエンド ユーザーを混乱させ、独自のコードを不必要に複雑にします。誰もあなたに感謝しません。1 つのスタイルを選択し、それに固執します。

オブジェクト指向プログラミングに固執することを選択したと仮定しましょう。次に、モジュールが機能してテストされたら、OO インターフェイスの代わりにエクスポート可能な関数を提供する 2 番目のモジュールを作成できます。2 番目のモジュールは、おそらく単純な古い Perl で記述でき、オブジェクト指向モジュールのラッパーとして機能します。

例として、読みやすくするために (XS ではなく) 純粋な Perl を使用します。

use v5.14;

package MyStuff::Maths::OO {
   use Class::Tiny qw(number);
   sub cosine {
      my $self   = shift;
      my $number = $self->number;
      ...;
      return $cosine;
   }
}

package MyStuff::Maths::Functional {
   use Exporter::Shiny qw(cosine);
   sub cosine {
      my $obj = ref($_[0]) ? $_[0] : MyStuff::Maths::OO->new(number => $_[0]);
      return $obj->cosine;
   }
}

エンド ユーザーは、次のように OO インターフェイスを使用することを選択できます。

use v5.14;
use MyStuff::Maths::OO;

my $obj = MyStuff::Maths::OO->new(number => 0.5);
say $obj->cosine;

または、機能インターフェースを使用します。

use v5.14;
use MyStuff::Maths::Functional -all;

say cosine(0.5);
于 2014-10-23T12:03:44.527 に答える