2017-05-06 28 views
6

Perl 6 docs은 일련의 유형을 나열합니다. 어떤 것은 Str과 같이 더 복잡한 박스/박스 작업을합니다.Perl 6 NativeCall 구조체에 대한 사용자 모드 유형 추가

박스/언 박싱에 대한 내 자신의 루틴을 지정하여 내 자신의 유형을 정의 할 수 있습니까? 특정 프로젝트의 경우, 필자는 재사용하고 기본적으로 접근 자 함수를 반복적으로 잘라내거나 붙여 넣는 여러 유형이 있습니다.

예를 들어, C Struct은 time_t을 사용하고 DateTime에서 /로 이동하는 접근 자 메서드를 연결합니다. 또 다른 예는 쉼표로 구분 된 목록입니다. 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 

이 나는 ​​펄 틱 방식으로 CStruct의 다양한 분야 설정할 수 있습니다 (NO 좌변을,하지만 난 매개 변수로에 전달할 수), 작동 .

이제 많은 구조체의 많은 필드에 time_t, FooType_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;