如何使用 NativeCall 缓解 Rakudo 中的错误?
How to mitigate a bug in Rakudo with NativeCall?
我希望能够在 class 中使用双指针和 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 部分中的错误(这就是我这样写的原因)?
失败的原因与失败的原因相同:
class Foo {...}
BEGIN Foo ~~ Bool; # <------
class Foo{
}
部分问题似乎是在调用 Pointer.^parameterize
方法时 Foo
尚未组合。
因此它还不是 Any
的子类型。 (甚至 Mu
)
解决方法是在使用 Pointer[::?CLASS]
.
之前在 BEGIN
移相器中添加 .^compose
调用
class Foo is repr('CPointer') {
BEGIN ::?CLASS.^compose;
my Pointer[::?CLASS] $foo .= new;
}
我的猜测是,真正的解决办法是将 Bool.ACCEPTS(Bool:U: \topic)
候选人更改为 Bool.ACCEPTS(Bool:U: Mu \topic)
。
我认为这是因为这也失败了,错误基本相同:
Mu ~~ Bool
我希望能够在 class 中使用双指针和 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 部分中的错误(这就是我这样写的原因)?
失败的原因与失败的原因相同:
class Foo {...}
BEGIN Foo ~~ Bool; # <------
class Foo{
}
部分问题似乎是在调用 Pointer.^parameterize
方法时 Foo
尚未组合。
因此它还不是 Any
的子类型。 (甚至 Mu
)
解决方法是在使用 Pointer[::?CLASS]
.
BEGIN
移相器中添加 .^compose
调用
class Foo is repr('CPointer') {
BEGIN ::?CLASS.^compose;
my Pointer[::?CLASS] $foo .= new;
}
我的猜测是,真正的解决办法是将 Bool.ACCEPTS(Bool:U: \topic)
候选人更改为 Bool.ACCEPTS(Bool:U: Mu \topic)
。
我认为这是因为这也失败了,错误基本相同:
Mu ~~ Bool