Search code examples
ncursesffirakunativecall

Native calling interface: how to translate "wchar_t"?


I would like to use the ncurses int addwstr(const wchar_t *wstr); function in Perl6.

How could I get a Perl 6 signatures which conveys const wchar_t *wstr of addwstr?

use v6;
use NativeCall;

constant LIB = 'libncursesw.so.5';

sub addwstr(  ?  ) returns int32 is native(LIB) is export {*};

Solution

  • wchar_t is 32 bits on my machine. From the NativeCall doco, you can declare an array of them and the array name will act as the pointer;

    #!/usr/bin/env perl6
    use v6;
    use NCurses;                   # To get iniscr(), endwin() etc
    use NativeCall;
    
    # Need to run setlocale from the C library
    my int32 constant LC_ALL = 6;           # From locale.h
    my sub setlocale(int32, Str) returns Str is native(Str) { * }
    
    constant LIB = 'libncursesw.so.5';
    sub addwstr(CArray[int32]) returns int32 is native(LIB) { * }
    
    # The smiley        : Codepoint 0x263a
    # Latin space       : Codepoint 0x20  (Ascii decimal ord 32)
    # Check mark (tick) : Codepoint 0x2713
    
    my CArray[int32] $wchar_str .= new(0x263a, 0x20, 0x2713);
    
    setlocale(LC_ALL, "");
    initscr();
    move(2,2);
    addwstr( $wchar_str );
    nc_refresh;
    while getch() < 0 {};
    endwin;
    

    This prints "☺ ✓" on my machine. It doesn't work without the call to setlocale.

    As an aside, you don't have to use the 'w' functions - you can just pass normal perl6 strings (presumably encoded UTF-8) and it just works. This produces the same result;

    #!/usr/bin/env perl6
    use v6;
    use NCurses;
    use NativeCall;
    
    # Need to run setlocale from the standard C library
    my int32 constant LC_ALL = 6;           # From locale.h
    my sub setlocale(int32, Str) returns Str is native(Str) { * }
    
    my $ordinary_scalar = "☺ ✓";
    
    setlocale(LC_ALL, "");
    initscr();
    move(2,2);
    addstr( $ordinary_scalar );   # No 'w' necessary
    nc_refresh;
    while getch() < 0 {};
    endwin;