如何使用NativeCall缓解Rakudo中的错误?

时间:2019-02-05 20:11:00

标签: c perl6 raku nativecall

我希望能够在具有REPR CStruct / CPointer的类中使用双指针:

typedef struct CipherContext {
          void    *cipher;
    const uint8_t *key;
          size_t   key_len;
    const uint8_t *path;
          size_t   path_len;
          size_t   block_size;
          void    *handle;

          int      (*cipher_init)(void **, const uint8_t *, size_t);
          int      (*cipher_encode)(void *, const uint8_t *, uint8_t *, size_t);
          int      (*cipher_decode)(void *, const uint8_t *, uint8_t *, size_t);
          void     (*cipher_free)(void *);
    const uint8_t *(*cipher_strerror)(int);
} CipherContext;

      int            cipher_context_init(CipherContext **, const uint8_t *, size_t, const uint8_t *, size_t, size_t);
      int            cipher_context_encode(CipherContext *, const uint8_t *, uint8_t *, size_t);
      int            cipher_context_decode(CipherContext *, const uint8_t *, uint8_t *, size_t);
      void           cipher_context_free(CipherContext *);
const uint8_t       *cipher_context_strerror(int);

Perl 6代码:

method new(Blob :$key!, Str :$path!, Int :$block-size!) {
    my Pointer[::?CLASS]     $ptr     .= new;
    my Int                   $err      = cipher_context_init($ptr, $key, $key.elems, $path, $path.codes, $block-size);
    return $ptr.deref unless $err;

    my Str $errstr = cipher_context_strerror($err) || do {
        my &cipher-strerror = nativecast(:(int32 --> Str), $!cipher-strerror);
        cipher-strerror($err)
    };
    die "Failed to initialize cipher context: $errstr";
}

submethod DESTROY() {
    cipher_context_free(self)
}

短打高尔夫球:

use v6.d;
use Nativecall;

class Foo is repr('CPointer') { 
    my Pointer[::?CLASS] $foo .= nw;
}

由于bug in Rakudo,只有我不知道该怎么做。有没有更好的方法可以处理代码的C部分中的错误(这就是为什么我要像这样编写它)?

1 个答案:

答案 0 :(得分:5)

失败的原因与失败相同:

SORT_NUMERIC

部分问题似乎是当调用class Foo {...} BEGIN Foo ~~ Bool; # <------ class Foo{ } 方法时,Foo尚未组成。

因此,它还不是Pointer.^parameterize的子类型。 (甚至是Any

一种解决方法是在使用Mu之前在.^compose移相器中添加BEGIN调用。

Pointer[::?CLASS]

我的猜测是,真正的解决方法是将class Foo is repr('CPointer') { BEGIN ::?CLASS.^compose; my Pointer[::?CLASS] $foo .= new; } 候选人更改为Bool.ACCEPTS(Bool:U: \topic)

我认为这是因为它也因基本相同的错误而失败:

Bool.ACCEPTS(Bool:U: Mu \topic)