9

我正在尝试在 Perl 6 中声明以下 C 结构:

struct myStruct
{
    int A[2]; //<---NEED to declare this
    int B;
    int C;
};

我的问题是我不知道如何int A[2];使用内置的 NativeCall api 声明该部分。

所以我所拥有的是:

class myStruct is repr('CStruct') {
    has CArray[int32] $.A;
    has int32 $.B;
    has int32 $.C;
};

但是,我知道该has CArray[int32] $.A;部分是错误的,因为它没有在我的结构中声明仅占用 2 个int32大小的部分。

4

4 回答 4

6

更新 2:事实证明,在我第一次发布此答案时,这不起作用,因此发表了评论。我没有测试它,但它肯定可以按照 Tobias 的回答将CStruct 中的内联 CArray 传递给使用 NativeCall 的共享库。\o/


我没有对此进行测试,但这在使用 Rakudo 编译器版本 2018.05 时应该可以工作:

use NativeCall;
class myStruct is repr('CStruct') {
    HAS int32 @.A[2] is CArray;
    has int32 $.B;
    has int32 $.C;
}
  • HAS而不是has使属性内联而不是指针;

  • int32而不是int因为 Perl 6int类型与 C 的int类型不同,而是特定于平台(通常是 64 位);

  • @而不是$将属性标记为存在Positional(“支持按索引查找值”)而不是标量(被视为单一事物);

  • [2]将位置数据“塑造”为具有 2 个元素;

  • is CArray绑定 aCArray作为位置数据的容器逻辑;

  • 这个从今年 4 月开始的提交连接了is repr('CStruct')使用声明的属性信息来适当地分配内存。

Fwiw 我通过搜索#perl6 日志发现了此功能,并CArray通过搜索 Rakudo 提交的提交消息标题发现它已登陆 master 和 2018.05 。

于 2018-06-07T15:51:12.320 回答
4

请参阅在 Perl 6 NativeCall CStruct 中声明数组

还有其他方法,但最简单的方法是代替数组,只需声明每个单独的项目。

class myStruct is repr('CStruct') {
    has int32 $.A0;
    has int32 $.A1;
    ... as many items as you need for your array ...
    has int32 $.B;
    has int32 $.C;
};
于 2018-06-07T01:52:16.233 回答
3

所以我对此做了一些实验并查看了文档,看起来 CArray 类型不像 Perl6 数组那样处理整形。

你得到的最接近的东西是分配构造函数,它在数组中预分配空间,但它不强制大小,所以你可以添加更多东西。

您的类定义很好,但您想在子方法中分配数组BUILD

https://docs.raku.org/language/nativecall#Arrays

(进一步思考)

你可以有两个对象。一个用于内部,一个用于结构。

Struct 有一个CArray[int32]数组。内部数据对象有一个整形 int32 cast array my int3 @a[2]。然后你只需要在两者之间复制。

getter 和 setter 存在于 main 对象上,而您只是在想与 lib 对话时才使用 struct 对象?

于 2018-06-06T16:23:04.323 回答
1

这并没有真正声明一个固定大小的数组,而是对其值的大小进行了限制:您可以尝试使用where来限制数组的大小。CArray不是位置的(因此不能用@印记声明),但它确实有elems方法.

use NativeCall; 
my CArray[int32] $A where .elems < 2

也就是说,至少在语法上是正确的。这是否会在其他地方破坏该程序还有待观察。你能试试吗?

于 2018-06-06T16:45:22.470 回答