如何在Perl 6中声明固定大小的本机数组?

时间:2018-06-06 14:39:45

标签: perl6 nativecall

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

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

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

所以我拥有的是:

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

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

4 个答案:

答案 0 :(得分:6)

更新2:事实证明,这在我第一次发布这个答案时没有用,因此评论。我仍未尚未对其进行测试,但根据Tobias对Passing an inlined CArray in a CStruct to a shared library using 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 6 int类型与C的int类型不同,而是特定于平台(通常是64位);

  • @而不是$将该属性标记为Positional(“支持按索引查找值”)而不是标量(将其视为单一内容)

  • [2]“定位”位置数据以包含2个元素;

  • is CArrayCArray绑定为位置数据的容器逻辑;

  • This commit from April this year连接is repr('CStruct')以使用声明的属性信息来正确分配内存。

Fwiw我从a search of the #perl6 logs for CArray发现了这个功能,发现它已经从a search of Rakudo commits for the commit message title登陆到主人和2018.05。

答案 1 :(得分:4)

请参阅Declaring an array inside a 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;
};

答案 2 :(得分:3)

所以我已经对此进行了一些实验并查看了文档,看起来CArray类型的处理形式与Perl6 Arrays不同。

你最接近它的是分配构造函数,它在数组中预先分配空间,但它没有强制执行大小,因此你可以添加更多东西。

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

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

(进一步思考)

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

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

getter和setter存在于主对象上,当你想与lib交谈时,你使用struct对象?

答案 3 :(得分:1)

这并没有真正声明一个固定大小的数组,而是对其值的大小设置了约束:您可以尝试使用where来约束数组的大小。 CArray不是位置(因此不能用@ sigil声明)但它确实有elems method

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

至少,语法上是正确的。是否在其他地方打破了该计划还有待观察。你能试试吗?