您可以使用 Raku 函数包装本机函数:
sub history ( Pointer[Internal] $a, Pointer[Event] $b, int32 $flag, $c? --> int32 ){
given $flag {
when 0|2 {
sub history (Pointer[Internal], Pointer[Event], int32 --> int32) is native(…) {}
history( $a, $b, $flag )
}
when 1|3 {
sub history (Pointer[Internal], Pointer[Event], int32, int32 --> int32) is native(…) {}
history( $a, $b, $flag, $c )
}
when 4 {
sub history (Pointer[Internal], Pointer[Event], int32, Str --> int32) is native(…) {}
history( $a, $b, $flag, $c )
}
}
}
或者您可以将每个版本包装在自己的多重中:
# Note the flag value ---------------------------------------+
# |
# V
multi sub history ( Pointer[Internal] $a, Pointer[Event] $b, 0 --> int32 ){
sub history (Pointer[Internal], Pointer[Event], int32 --> int32) is native(…) {}
history( $a, $b, 0 )
}
multi sub history ( Pointer[Internal] $a, Pointer[Event] $b, 2 --> int32 ){
sub history (Pointer[Internal], Pointer[Event], int32 --> int32) is native(…) {}
history( $a, $b, 2 )
}
multi sub history ( Pointer[Internal] $a, Pointer[Event] $b, int32 $flag where 1|3, int32 $c --> int32 ){
sub history (Pointer[Internal], Pointer[Event], int32, int32 --> int32) is native(…) {}
history( $a, $b, $flag, $c )
}
multi sub history ( Pointer[Internal] $a, Pointer[Event] $b, 4, Str:D $c --> int32 ){
sub history (Pointer[Internal], Pointer[Event], int32, Str --> int32) is native(…) {}
history( $a, $b, 4, $c )
}
您甚至可以根据参数确定要给出的正确标志。这只有在每个签名只有一个标志时才有效。
(因此以下示例不遵循上述 where0
并2
具有相同的签名。)
multi sub history ( Pointer[Internal] $a, Pointer[Event] $b --> int32 ){
sub history (Pointer[Internal], Pointer[Event], int32 --> int32) is native(…) {}
history( $a, $b, 0 )
}
multi sub history ( Pointer[Internal] $a, Pointer[Event] $b, int32 $c --> int32 ){
sub history (Pointer[Internal], Pointer[Event], int32 --> int32) is native(…) {}
history( $a, $b, 1, $c )
}
multi sub history ( Pointer[Internal] $a, Pointer[Event] $b, Str:D $c --> int32 ){
sub history (Pointer[Internal], Pointer[Event], int32, Str --> int32) is native(…) {}
history( $a, $b, 4, $c )
}
您可以编写具有不同名称的包装器:
sub foo ( Pointer[Internal] $a, Pointer[Event] $b --> int32 ){
sub history (Pointer[Internal], Pointer[Event], int32 --> int32) is native(…) {}
history( $a, $b, 0 )
}
sub bar ( Pointer[Internal] $a, Pointer[Event] $b, int32 $c --> int32 ){
sub history (Pointer[Internal], Pointer[Event], int32 --> int32) is native(…) {}
history( $a, $b, 1, $c )
}
sub baz ( Pointer[Internal] $a, Pointer[Event] $b, Str:D $c --> int32 ){
sub history (Pointer[Internal], Pointer[Event], int32, Str --> int32) is native(…) {}
history( $a, $b, 4, $c )
}
您可以使用is symbol
.
sub foo (Pointer[Internal], Pointer[Event], int32 --> int32) is native(…) is symbol<history> {}
sub bar (Pointer[Internal], Pointer[Event], int32, int32 --> int32) is native(…) is symbol<history> {}
sub baz (Pointer[Internal], Pointer[Event], int32, Str --> int32) is native(…) is symbol<history> {}
您还可以nativecast
在包装函数中使用和生成的 Signature 对象:
sub history ( Pointer[Internal] $a, Pointer[Event] $b, int32 $flag, $c? --> int32 ){
my \I32 = Parameter.new( type => int32 );
my \PI = Parameter.new( type => Pointer[Internal] );
my \PE = Parameter.new( type => Pointer[Event] );
my \STR = Parameter.new( type => Str );
my @params = ( PI, PE, I32 );
given $flag {
when 0|2 {
}
when 1|3 {
@params.push( I32 );
}
when 4 {
@params.push( STR );
}
}
my \signature = Signature.new( params => @params.List, returns => int32 );
# fill this out -----------V
my \history-ptr = cglobal( …, 'history', Pointer );
my &history = nativecast( signature, history-ptr );
history( $a, $b, $flag, ($c if +@params == 4) );
}
这就是您可能为 Cprintf
或scanf
.
无论您使用上述哪种方法,您都需要某种方法来确定需要调用的变体。
即使在 C 中,也必须有一种方法可以根据当前或先前的参数来确定参数的数量和类型。
printf
参数的数量和类型是基于第一个参数的格式。
AC 函数可以通过尾随空参数来确定参数的数量。在这种情况下,你必须告诉 Raku。
无论底层的外部函数如何处理va_args
,您都必须将该算法以某种形式复制到 Raku 中。它不能只是猜测。
如果你有几个工作相似的外部函数,你可以为它们创建一个包装器生成器。