jjmerelo
jjmerelo

Reputation: 23527

How to correctly use CPointer and CStruct in NativeCall interface

I am trying to get this example of NativeCall running:

use NativeCall;

class p_timespec is repr('CPointer') {
    has uint32 $.tv_sec;
    has long $.tv_nanosecs;
}

sub clock_gettime(uint32 $clock-id, p_timespec $tspec --> uint32) is native(Str) { * };

my p_timespec $this-time;

my $result = clock_gettime( 0, $this-time);

say "$result, $this-time";

It simply segfaults, which is what happens when you use pointers and you should not. In this case, it's probably due to the declaration of p_timespec; I have actually declared it as a CPointer, although the struct should be OK. However, from the segmentation fault I can't fathom what's really wrong. Can someone help?

Upvotes: 8

Views: 169

Answers (1)

Jonathan Worthington
Jonathan Worthington

Reputation: 29454

There's two things wrong here.

  1. The CStruct representation should be used
  2. You need to make an instance of the structure for it to fill out with data, otherwise you're passing a null pointer

This seems to work:

use NativeCall;

class p_timespec is repr('CStruct') {
    has uint32 $.tv_sec;
    has long $.tv_nanosecs;
}

sub clock_gettime(uint32 $clock-id, p_timespec $tspec --> uint32) is native(Str) { * };

my p_timespec $this-time .= new;

my $result = clock_gettime( 0, $this-time);

say "$result, $this-time.tv_sec(), $this-time.tv_nanosecs()";

As for debugging, Rakudo's installation process also installs a perl6-gdb-m and a perl6-valgrind-m; the latter, while slow, will tend to provide some useful information on memory errors.

Upvotes: 9

Related Questions