I try to use libXL from Perl 6 (latest version) with NativeCall
.
I can't get utf-8 to correctly save the created xlsx file.
Only CArray[uint16]
seems to work nor Str is encoded('utf8') nor CArray[uint8]
.
Best result is saved workbook, sheet name and text; but very often they end in special symbols. Even setting the key does work "very often".
My guess was that utf-8 is needed but CArray[uint16]
always gives two bytes, while utf-8 is a dynamic format. My guess also is, that my signatures for libXL.dll may be wrong.
I also tried the A-DLL-versions of the functions which worked for xls, but I want to get an xlsx (XML format).
I tried to change the sub signatures for NativeCall
and tried the given variables in different formats.
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();
- sometimes, nothing is saved, and code ends from Perl 6 with a non 0 code
- sometimes, file name ends in a special character (maybe depending on the Nr.)
- the A-functions (ASCII) do work
This code shows how to call a *W function from the Windows API. Chances are this will work with your library too: