On 2019-12-29 14:56, ToddAndMargo via perl6-users wrote:
Hi All,
This is my keeper on Native Call.
-T
<perl6.Native.Call.Notes.txt>
Raku: Native Call notes:
Really poor reference: https://docs.raku.org/language/nativecall
1) Kernel32.dll call variables with a "p" in them are "C" pointers.
LSTATUS RegOpenKeyExW(
HKEY hKey,
LPCWSTR lpSubKey,
DWORD ulOptions,
REGSAM samDesired,
PHKEY phkResult
);
LPCWSTR and PHKEY in the above would be "C" pointers.
A) Native Call converts Raku variables into C Pointer for you
B) NativeCall converts the pointers to their contents of a
returned “C” variable for you
2) to pass a "C" NULL to Native Call, send it a numerical zero.
Note: in “C”, a NULL is a pointer whose value is zero
3) a “C” string is an array of characters terminated with chr(0)
4) Kernel32.dll calls with a “W” in them use UTF16 `uint16` values
in their strings. The rest you can use UTF8 `uint8`. Most of
the time they are interchangeable if you are using standard
characters.
Use the following to convert a Raku strings, `abcdefg` below,
into a “C” string
UTF8: my $L = CArray[uint8].new("abcdefg".encode.list);
UTF16: my $M = CArray[uint16].new("abcdefg".encode.list);
Native Call is tack the chr(0) at the end for you.
5) create two line to pass a call to Native Call (see 1) above for
the call definition):
constant WCHAR := uint16;
constant DWORD := int32;
sub RegQueryValueExW(
DWORD,
WCHARS,
DWORD,
DWORD,
DWORD is rw,
DWORD is rw
)
is native("Kernel32.dll")
is symbol("RegQueryValueExW")
returns DWORD
{ * };
$RtnCode = RegQueryValueExW(
$Handle, $lpValueName, 0, 0, $lpData, $lpcbData );
$RtnCode is the Windows return error code. Note: 0 is success
$lpData is the actual data converted from the “C” pointer
$lpcbData is the converted number of bytes in $lpData’s
converted data
</perl6.Native.Call.Notes.txt>
Today's revised revision:
4) Kernel32.dll calls with a “W” in them use UTF16 `uint16` values
in their strings. The rest you can use UTF8 `uint8`. Most of
the time they are interchangeable if you are using standard
characters.
Use the following to convert a Raku strings, `abcdefg` below,
into a “C” string
UTF8: my $L = CArray[uint8].new("abcdefg".encode.list);
UTF16: my $M = CArray[uint16].new("abcdefg".encode.list);
Native Call is tack the chr(0) at the end for you, most of the time
To tack a nul on the end (two nuls won't hurt anything)
my $M = CArray[uint16].new("abcdefg".encode.list); $M[$M.elems] = 0
Note: you can't use `push` as it is an "immutable 'List'"
A sub to convert and tack on the nul:
constant WCHAR = uint16;
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;
}
--
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Computers are like air conditioners.
They malfunction when you open windows
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~