gpt4 book ai didi

raku - 将函数指针放入 Perl6 NativeCall CStruct

转载 作者:行者123 更新时间:2023-12-01 07:58:44 25 4
gpt4 key购买 nike

试图与一个 C 库接口(interface),该库采用一个结构,该结构带有一堆指向它在各个点调用的函数的指针。

像这样的东西:

struct callbacks {
int (*foo)(int);
int (*bar)(int);
}

int set_callbacks(callbacks *cbs);

我可以进行回调:
sub foo-callback(int32 --> int32) {...}
sub bar-callback(int32 --> int32) {...}

如果这可行,那就太酷了:
class Callbacks is repr<CStruct>
{
has &.foo (int32 --> int32);
has &.bar (int32 --> int32);
}

但事实并非如此。我正在尝试做一些事情:
class Callbacks is repr<CStruct>
{
has Pointer $.foo;
has Pointer $.bar;
}

并将它们设置为 nativecast(Pointer, &foo-callback)或类似的,但我不能
似乎强制他们在那里。

除了编写一个小 C 函数来获取所有 Perl 6 函数指针并将它们插入 C 中的结构之外,还有什么方法可以做到这一点?

最佳答案

我仍然找不到正式的方法来做到这一点,但我想出了一个解决方法。

声明 sprintf 的版本它需要一个正确类型的函数指针(因此它将正确设置调用 shim),但作弊并让 sprintf 将指针作为数字( %lld )返回给我,我可以填充指针。

class Callbacks is repr<CStruct>
{
has Pointer $.foo;
has Pointer $.bar;

sub sprintf(Blob, Str, & (int32 --> int32) --> int32) is native {}

submethod BUILD(:&foo, :&bar)
{
my $buf = buf8.allocate(20);
my $len = sprintf($buf, "%lld", &foo);
$!foo := Pointer.new($buf.subbuf(^$len).decode.Int);
$len = sprintf($buf, "%lld", &bar);
$!bar := Pointer.new($buf.subbuf(^$len).decode.Int);
}
}

sub foo-callback(int32 $x --> int32) {...}
sub bar-callback(int32 $x --> int32) {...}

my $callbacks = Callbacks.new(foo => &foo-callback,
bar => &bar-callback);

如果您有多个具有不同签名的回调,只需声明 sprintf对于您需要的每个 C 调用签名,例如:
sub sprintf-ii(Blob, Str, & (int32 --> int32) --> int32)
is native is symbol('sprintf') {}

sub sprintf-isi(Blob, Str, & (int32, Str --> int32) --> int32)
is native is symbol('sprintf') {}

并调用右边 sprintf-*对于您需要的每个回调指针。

可能有比使用指向数字的指针到字符串到数字到指针的指针来回更简单的方法,但现在这可以解决问题。

关于raku - 将函数指针放入 Perl6 NativeCall CStruct,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48772284/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com