Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Raku/Perl6: how do you code a NULL with NativeCall

https://docs.perl6.org/language/nativecall

 "As you may have predicted by now, a NULL pointer
 is represented by the type object of the struct type."

https://learn.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regqueryvalueexw

 C++
 LSTATUS RegQueryValueExW(
   HKEY    hKey,
   LPCWSTR lpValueName,
   LPDWORD lpReserved,
   LPDWORD lpType,
   LPBYTE  lpData,
   LPDWORD lpcbData
 );

 lpReserved
 This parameter is reserved and must be NULL.

With "native", how do I satisfy the "NULL" requirement?

constant WCHAR   := uint16;
constant DWORD   := int32;

sub RegQueryValueExW( DWORD, WCHARS, DWORD, DWORD, DWORD is rw, DWORD is rw ) is native("Kernel32.dll") returns DWORD { * };

$RtnCode = RegQueryValueExW( $Handle, $lpValueName, int32, REG_DWORD, $lpData, $lpcbData );

"int32" returns:

Cannot unbox a type object (int32) to int in method
CALL-ME at C:\rakudo\share\perl6\sources \947BDAB9F96E0E5FCCB383124F9
23A6BF6F8D76B (NativeCall) line 587

Many thanks, -T

like image 438
Todd Avatar asked Dec 27 '19 12:12

Todd


1 Answers

To pass a pointer to a DWORD you can use a CArray[DWORD]. For example, here I created a test library libmylib.so with a foo() function taking DWORD * (aka int32_t *) argument:

#include <stdio.h>
#include <stdint.h>

void foo (int32_t *bar) {
    if ( bar == NULL ) {
        printf( "Got NULL pointer\n" ); 
    }
    else {
        printf("Got bar: %d\n", bar[0]);
    }
}

Then test a Raku interface to this library using:

use v6;
use NativeCall;

constant DWORD := int32;
sub foo(CArray[DWORD]) is native("./libmylib.so") { * };
my @bar := CArray[DWORD].new;
@bar[0]  = 1;
foo(@bar);
foo(CArray[DWORD]);  # <-- Use a type object to pass a NULL pointer

Output:

Got bar: 1
Got NULL pointer
like image 60
Håkon Hægland Avatar answered Oct 24 '22 09:10

Håkon Hægland