Как я могу правильно использовать libXL из Perl 6, используя NativeCall? - PullRequest
4 голосов
/ 18 октября 2019

Я пытаюсь использовать libXL из Perl 6 (последняя версия) с NativeCall. У меня нет utf-8, чтобы правильно сохранить созданный файл xlsx. Кажется, что работает только CArray [uint16], ни кодируется Str ('utf8'), ни CArray [uint8]. Лучший результат - сохранение рабочей книги, имени листа и текста;но очень часто они заканчиваются специальными символами. Даже установка ключа работает «очень часто».

Я предполагаю, что utf-8 необходим, но CArray [uint16] всегда дает два байта, тогда как utf-8 - это динамический формат. Я также полагаю, что мои подписи для libXL.dll могут быть неправильными.

Я также пробовал A-DLL-версии функций, которые работали для xls, но я хочу получить xlsx (формат XML).

Есть идеи по этому поводу?

Я пытался изменить подписи для NativeCall и пробовал заданные переменные в разных форматах.

use v6;

use NativeCall;

constant PathLibXL = "C:/....../libxl-3.8.5.0/bin64/libxl.dll";

sub xlBookSaveW(int32, CArray[uint16])                                                                  returns uint8                                           is native(PathLibXL) {*};       #       int xlBookSave(BookHandle handle, const wchar_t* filename)
sub xlBookAddSheetW(int64, CArray[uint16])                                                          returns int64                                           is native(PathLibXL) {*};       #       SheetHandle xlBookAddSheet(BookHandle handle, const wchar_t* name, SheetHandle initSheet)
sub xlBookErrorMessageW(int64)                                                                                  returns Str is encoded('utf8')      is native(PathLibXL) {*};       #       const char* xlBookErrorMessage(BookHandle handle)
sub xlBookReleaseW(int64)                                                                                                                                                                   is native(PathLibXL) {*};       #       void xlBookRelease(BookHandle handle)
sub xlBookSetKeyW(int64, CArray[uint16], CArray[uint16])                                                                                                    is native(PathLibXL) {*};       #       void xlBookSetKey(BookHandle handle, const wchar_t* name, const wchar_t* key)
sub xlCreateBookW()                                                                                                         returns int64                                       is native(PathLibXL) {*};       #       Book* xlCreateBook()
sub xlCreateXMLBookW()                                                                                                  returns int64                                       is native(PathLibXL) {*};       #       Book* xlCreateBook()
sub xlSheetWriteStrW(int64, int64, int64, CArray[uint16], int64)                returns int64                                           is native(PathLibXL) {*};       #       int xlSheetWriteStr(SheetHandle handle, int row, int col, const wchar_t* value, FormatHandle format)


sub test-nativeW(){
    my $format = 'utf-8';   #   utf8 utf16 utf16le utf16be utf8-c8 iso-8859-1 windows-1251 windows-1252 windows-932 ascii
    my $Nr = (11111..99999).rand.Int;

    my $sheetName16 = CArray[uint16].new("SheetTest".encode($format).list);
    my $text                = CArray[uint16].new("Hello, world!".encode($format).list);
    my $savePath16  = CArray[uint16].new("C:/Temp/Test.$Nr.perl6.xlsx".encode($format).list);


    my $book = xlCreateXMLBookW();
    if $book > 0 {
        say "savePath16:" ~ $savePath16;

        my $name = CArray[uint16].new("DELETED".encode($format).list);
        my $key  = CArray[uint16].new("DELETED".encode($format).list);

        xlBookSetKeyW($book, $name, $key);

        say "book:" ~ $book;
        say "sheetName16: $sheetName16";

        my $sheet = xlBookAddSheetW($book, $sheetName16);

        if $sheet > 0 {
            say "sheet: $sheet";

            xlSheetWriteStrW($sheet, 0, 0, $text, 0);

        }else{
            say "sheet: $sheet";

            my $errMsg = xlBookErrorMessageW($book);

            say "error:{ $errMsg.Str }";
        }

        say "C:/Temp/Test.$Nr.perl6.xlsx".encode($format).Str;

        my $R = xlBookSaveW($book, $savePath16);

        if $R > 0 {
            say "releasing book...";
            xlBookReleaseW($book)
        }

    }else{
        say "book:" ~ $book;

        my $errMsg = xlBookErrorMessageW($book);

        say "error:{ $errMsg.Str }";
    }
}

test-nativeW();
  • иногда,ничего не сохраняется и код заканчивается в Perl 6 кодом, отличным от 0
  • иногда, имя файла заканчивается специальным символом (возможно, в зависимости от Nr.)
  • , которые выполняют A-функции (ASCII)работа

1 Ответ

3 голосов
/ 18 октября 2019

Этот код показывает, как вызвать функцию * W из Windows API. Скорее всего, это будет работать и с вашей библиотекой:

use NativeCall;

constant WCHAR              = uint16;
constant INT                = int32;
constant UINT               = uint32;
constant HANDLE             = Pointer[void];
constant LPWCTSTR           = CArray[WCHAR];
constant MB_ICONEXCLAMATION = 0x00000030;

sub MessageBoxW( HANDLE, LPWCTSTR, LPWCTSTR, UINT ) is native('user32') returns INT { * };

MessageBoxW( my $handle, to-c-str("๘❤ Raku is awesome ❤๖"), to-c-str("Hellö Wαrld"), MB_ICONEXCLAMATION );

sub to-c-str( Str $str ) returns CArray[WCHAR]
{
    my @str := CArray[WCHAR].new;
    for ( $str.comb ).kv -> $i, $char { @str[$i] = $char.ord; }
    @str[ $str.chars ] = 0;
    @str;
}
...