Родной интерфейс вызова: как перевести wchar_t?

Я хотел бы использовать функцию ncurses int addwstr(const wchar_t *wstr); в Perl6.

Как я могу получить подписи Perl 6, которые передают const wchar_t *wstr из addwstr?

use v6;
use NativeCall;

constant LIB = 'libncursesw.so.5';

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

person sid_com    schedule 04.03.2016    source источник
comment
Если я не ошибаюсь, это будет Str is encoded('utf32') в Linux.   -  person ElderBug    schedule 04.03.2016
comment
ElderBug: Это дает мне: Неизвестная кодировка строки для собственного вызова: utf32 в ... (в Linux).   -  person sid_com    schedule 04.03.2016
comment
Я на самом деле не Perl парень, поэтому я не уверен. wchar_t в Linux - это UTF-32. Может быть, это сработает с 'UTF-32' ?   -  person ElderBug    schedule 04.03.2016
comment
Чтение NativeCall.pm6 похоже, что кодировка utf32 не распознается собственным механизмом вызова.   -  person sid_com    schedule 04.03.2016
comment
Кажется, это тупик. Будет ли работать для вас, если вы используете addstr вместо addwstr с Str is encoded('utf8') ? Или, может быть, вы могли бы преобразовать себя в UTF-32 в Perl, а затем перейти к addwstr как массиву int32.   -  person ElderBug    schedule 04.03.2016
comment
С Str is encoded('utf8') я все еще не получаю правильный вывод, и когда я пытаюсь сделать это с массивом, я получаю сообщение об ошибке: This representation (CArray) cannot unbox to a native string   -  person sid_com    schedule 04.03.2016
comment
Вы использовали addstr с utf8? Я думаю, вам нужно связать libncurses вместо libncursesw. Что касается массива, как он узнает, что натив ожидает строку? Вы где-то ставили подпись? Я не думаю, что он может прочитать это из «.so». Вы должны предоставить более подробную информацию (возможно, кто-то другой мог бы помочь вам быстрее, но что касается меня, мне нужны подробности). Кроме того, добавьте попытки, которые вы предприняли в вопросе (проще мне и другим, кто может помочь).   -  person ElderBug    schedule 04.03.2016
comment
Может быть, я понял, что вы сделали для массива. Вы правильно поставили определение как sub addwstr( CArray[int32] ) ? Кроме того, если вы сделали преобразование самостоятельно, убедитесь, что в конце массива есть терминал 0 (idk, если Perl уже сделал это для своих строк).   -  person ElderBug    schedule 04.03.2016
comment
Если вы знаете способ заставить эту работу работать, не могли бы вы опубликовать это как ответ.   -  person sid_com    schedule 05.03.2016
comment
Я пока не знаю. Вы должны добавить свои попытки к вопросу, потому что я не уверен, что вы на самом деле пробовали, поэтому я действительно не знаю, что на самом деле не работает. Добавьте код, в котором вы также используете эту функцию.   -  person ElderBug    schedule 05.03.2016


Ответы (1)


wchar_t на моей машине 32 бита. Из документа NativeCall вы можете объявить их массив, и имя массива будет действовать как указатель;

#!/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;

Это печатает «☺ ✓» на моей машине. Это не работает без вызова setlocale.

Кроме того, вам не нужно использовать функции 'w' — вы можете просто передавать обычные строки perl6 (предположительно закодированные в UTF-8), и это просто работает. Это дает тот же результат;

#!/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;
person Marty    schedule 14.03.2016
comment
Я не думаю, что это портативно. В Windows wchar_t — это uint16 в соответствии с docs.microsoft.com. /en-us/windows/desktop/midl/wchar-t - person Kaiepi; 08.08.2018