2017-05-06 8 views
6

Perl 6 docsには複数の種類のリストがあります。 Strのような一部のものは、より複雑なボックス/ボックス解除動作を持っています。Perl 6 NativeCall構造体のユーザーモードタイプを追加する

自分のタイプを定義して、ボックス/アンボックスに自分のルーチンを指定することはできますか?特定のプロジェクトでは、私は再利用しているタイプの束を持っており、基本的にはアクセサの機能を何度も切り取って貼り付けています。

たとえば、C Structはtime_tを使用し、アクセッサーメソッドをプラグインしてDateTimeに/からアクセスします。もう1つの例はコンマで区切られたリストです。私はArrayに/から行き、split/joinを自動的に処理したいと思います。

これを行うより良い方法はありますか?

編集:例を追加します。

constant time_t = uint64; 
constant FooType_t = uint16; 

enum FooType <A B C>; 

class Foo is repr('CStruct') is rw 
{ 
    has uint32 $.id; 
    has Str  $.name; 
    has FooType_t $.type; 
    has time_t $.time; 

    method name(Str $n?) { 
     $!name := $n with $n; 
     $!name; 
    } 

    method type(FooType $t?) { 
     $!type = $t with $t; 
     FooType($!type); 
    } 

    method time(DateTime $d?) { 
     $!time = .Instant.to-posix[0].Int with $d; 
     DateTime.new($!time) 
    } 
} 

my $f = Foo.new; 
$f.id = 12; 
$f.name('myname'); 
$f.type(B); 
$f.time(DateTime.new('2000-01-01T12:34:56Z')); 

say "$f.id() $f.name() $f.type() $f.time()"; 

# 12 myname B 2000-01-01T12:34:56Z 

これは動作しますが、私は、Perlっぽいな方法で(何の左辺値を、私はそれらをパラメータとして渡すことができます)CStructの様々なフィールドを設定することはできません。

今度は、たくさんの構造体の多くのフィールドにtime_tFooType_tなどを使用して、同じように動作させたいと思います。これらのメソッドを何度も繰り返しコピーする以外の方法がありますか?

多分マクロがここに役立つでしょうか?私はまだそれらを習得していない。

+0

メモリ管理はなり私がこれにいくらか近づくにつれて挑戦的です。 CStructを非常に素早く扱い、スマートなクラスを上に重ねるのが最も良いでしょう。 –

+0

ところで:私はNativeCallが大好きです。 Cライブラリとのインターフェイスがいかに簡単かは驚くべきことです。 –

答えて

8

属性の取得または保存時に自動属性変換を処理する特性を記述できます。次はあなたが始める必要があります。たとえば

multi sub trait_mod:<is>(Attribute:D $attr, :$autoconv!) { 
    use nqp; 
    my $name := $attr.name; 
    $attr.package.^add_method: $name.substr(2), do given $attr.type { 
     when .REPR eq 'P6int' { 
      method() is rw { 
       my $self := self; 
       Proxy.new: 
        FETCH => method() { 
         $autoconv.out(nqp::getattr_i($self, $self.WHAT, $name)); 
        }, 
        STORE => method ($_) { 
         nqp::bindattr_i($self, $self.WHAT, $name, 
          nqp::decont($autoconv.in($_))); 
        } 
      } 
     } 

     default { 
      die "FIXME: no idea how to handle {.^name}"; 
     } 
    } 
} 

を、time_tのユースケースを取る:

constant time_t = uint64; 

class CTimeConversion { 
    multi method in(Int $_ --> time_t) { $_ } 
    multi method in(DateTime $_ --> time_t) { .posix } 
    method out(time_t $_ --> DateTime) { DateTime.new($_) } 
} 

class CTimeSpan is repr<CStruct> { 
    has time_t $.start is autoconv(CTimeConversion); 
    has time_t $.end is autoconv(CTimeConversion); 
} 

は最後に、それを表示するためにいくつかのサンプルコードは動作します:

my $span = CTimeSpan.new; 
say $span; 
say $span.end; 

$span.end = DateTime.now; 
say $span; 
say $span.end; 
関連する問題