我正在尝试在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
个尺寸的部分。
答案 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 CArray
将CArray
绑定为位置数据的容器逻辑;
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
至少,语法上是正确的。是否在其他地方打破了该计划还有待观察。你能试试吗?