raku - 使用 NativeCall 将 CStruct 中的内联 CArray 传递给共享库
问题描述
这是“如何在 Perl 6 中声明固定大小的原生数组? ”的后续问题。
在那个问题中,讨论了如何将固定大小的数组合并到CStruct
. 在这个答案中,建议使用HAS
内联 aCArray
在CStruct
. 当我测试这个想法时,我遇到了一些奇怪的行为,在问题下方的评论部分无法解决,所以我决定将它写成一个新问题。这是我的 C 测试库代码:
slib.c:
#include <stdio.h>
struct myStruct
{
int A;
int B[3];
int C;
};
void use_struct (struct myStruct *s) {
printf("sizeof(struct myStruct): %ld\n", sizeof( struct myStruct ));
printf("sizeof(struct myStruct *): %ld\n", sizeof( struct myStruct *));
printf("A = %d\n", s->A);
printf("B[0] = %d\n", s->B[0]);
printf("B[1] = %d\n", s->B[1]);
printf("B[2] = %d\n", s->B[2]);
printf("C = %d\n", s->C);
}
要从中生成共享库,我使用了:
gcc -c -fpic slib.c
gcc -shared -o libslib.so slib.o
然后,Perl 6 代码:
p.p6:
use v6;
use NativeCall;
class myStruct is repr('CStruct') {
has int32 $.A is rw;
HAS int32 @.B[3] is CArray is rw;
has int32 $.C is rw;
}
sub use_struct(myStruct $s) is native("./libslib.so") { * };
my $s = myStruct.new();
$s.A = 1;
$s.B[0] = 2;
$s.B[1] = 3;
$s.B[2] = 4;
$s.C = 5;
say "Expected size of Perl 6 struct: ", (nativesizeof(int32) * 5);
say "Actual size of Perl 6 struct: ", nativesizeof( $s );
say 'Number of elements of $s.B: ', $s.B.elems;
say "B[0] = ", $s.B[0];
say "B[1] = ", $s.B[1];
say "B[2] = ", $s.B[2];
say "Calling library function..";
say "--------------------------";
use_struct( $s );
脚本的输出是:
Expected size of Perl 6 struct: 20
Actual size of Perl 6 struct: 24
Number of elements of $s.B: 3
B[0] = 2
B[1] = 3
B[2] = 4
Calling library function..
--------------------------
sizeof(struct myStruct): 20
sizeof(struct myStruct *): 8
A = 1
B[0] = 0 # <-- Expected 2
B[1] = 653252032 # <-- Expected 3
B[2] = 22030 # <-- Expected 4
C = 5
问题:
为什么
nativesizeof( $s )
给出 24(而不是 20 的期望值)?为什么
B
从 C 函数打印时结构中的数组内容与预期不符?
注意:
我正在使用 Ubuntu 18.04 和 Perl 6 Rakudo 版本 2018.04.01,但也使用版本 2018.05 进行了测试
解决方案
你的代码是正确的。我刚刚在 MoarVM 中修复了该错误,并向 rakudo 添加了测试,类似于您的代码:
在 C 中:
typedef struct {
int a;
int b[3];
int c;
} InlinedArrayInStruct;
在 Perl 6 中:
class InlinedArrayInStruct is repr('CStruct') {
has int32 $.a is rw;
HAS int32 @.b[3] is CArray;
has int32 $.c is rw;
}
请参阅这些补丁: https ://github.com/MoarVM/MoarVM/commit/ac3d3c76954fa3c1b1db14ea999bf3248c2eda1c https://github.com/rakudo/rakudo/commit/f8b79306cc1900b7991490eef822480f304a56d9
如果您不是直接从 github 的最新源构建 rakudo(以及 NQP 和 MoarVM),您可能需要等待将出现在此处的 2018.08 版本:https ://rakudo.org/files
推荐阅读
- android - Android Studio -- 无法标记目标目录“#”。期待要么'
' 或者 ' # _ ' 格式 - python-3.x - 构建仿真性能数据数据库
- linux - Bash 脚本不会在 Centos 8 中作为 cron.hourly 作业运行
- machine-learning - ResNet50 torchvision 实现在 CIFAR-10 上的准确性较低
- vim - 我在链接 brew 的 vim 版本时遇到问题
- c# - 从 html 按钮调用 C# 函数
- netlogo - Netlogo 模拟如何添加加油站?
- int - 循环内的 Nunjucks,将属性转换为 int 并按 int 排序?
- php - PayPal Checkout Button 间歇性问题未发布到 PayPal
- c# - 如果字段 2 为空,C# 使用字段 1 的值