如何从Raku传递CArray [of-struct]到C?

问题描述

我如何进行这项工作?

更新:在搜索了包括Raku规范测试的Github之后,在这里,我还没有找到任何传递CArray [of-structs]的示例。 Here there is a post by Christoph自2017年以来提供了“解决方法”。

Christoph的解决方案可能有效,但如果没有更好的解决方案,则在NativeCall中会更好。

在Github上有a Rakudo test that uses a int TakeAStructArray(Struct **structs),如果您可以编写一个C函数来重新包装其args以转发到TakeAnArrayOfStruct( struct Struct[]),这可能会有所帮助。

下面,JJMerelo怀疑我由于Rakudo中的错误而失败。

我有一个 C 函数,该函数使用与使用的timespec结构类似的timespec结构 在NativeCall文档中:

struct TS {

int show2(struct TS ts [2]){ printf(“ show2:(1)%ld%ld(2)%ld%ld \ n”, ts [0] .ot,ts [0] .one,ts [1] .ot,ts [1] .one); 返回0; } 从 C 调用时效果很好。

从Raku(沼泽地)打来的电话不起作用:

class TS is repr('CStruct') {
    has long $.ot;
    has long $.one;
}

sub show2( CArray[TS] --> int32) is native(
    '/home/rir/Raku/try-CArray/libshow.so'
    ) {*}

my $A = CArray[TS].new;
$A[1] = TS.new( :ot(50),:one(60));
$A[0] = TS.new( :ot(30),:one(40));
show2( $A);
say "  s/b 30 40 50 60\n";

没有错误,只是结果如下:

show2: (1)  94658691693328 94658695469968  (2) 0 0
  s/b 30 40 50 60

模拟功能int show2long( long i[2] )int showTS(int show1( struct TS *ts )起作用。

解决方法

前一段时间我遇到了这个确切的问题,这迫使我写了a workaround

简短答案,NativeCall尚不支持。

长答案:如上所述,有一种解决方法。如果您不想浏览我的代码,答案可以归结为:

使用Pointer

或者更好的是,一个Buf,然后使用NativeCall :: Blob的pointer-to

然后,您将使用以下例程作为位置来访问元素:

  # Cribbed from MySQL::Native. Thanks,ctilmes!
  method AT-POS(Int $field) {
    nativecast(
      T,Pointer.new( $!b + $field * nativesizeof(T) )
    )
  }

以及以下方法以适当的索引分配结构

  method bind (Int() $pos,T $elem) {
    my uint64 $p = $pos;

    memcpy(
      Pointer.new( $!b + $p * nativesizeof(T) ),nativecast(Pointer,$elem),nativesizeof(T)
    );
  }

这样的事情的基本实现是:

use NativeHelper::Blob;

class TypedBuffer {
  has Buf $!b;

  submethod BUILD ( :@array-of-structs ) {
    # Assumes that array contains homogeneous struct values!
    $!b = Buf.allocate(
      @array-of-structs.elems * nativesizeof( @a[0].WHAT )
    )
  }    

  method new (@array-of-structs) {
    self.bless( :@array-of-structs); 
  }

  method bind (Int() $pos,nativesizeof(T)
    );
  }

  method AT-POS(Int $field) {
    nativecast(
      T,Pointer.new( $!b + $field * nativesizeof(T) )
    )
  }

  method Pointer {
    pointer-to($!b);
  }

}

基本用法如下:

my $aos = TypedBuffer.new(@array-of-structs);  # Init
my $struct = $aos[0];                          # Retrieve first element
$aos.bind(2,$new-struct);                     # Replace third element
my-c-func($aos.Pointer);                       # Make call to a C Function

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...