I self nominate pm100/dyncall
dyncall allows interpreters, script based languages to dynamically call arbitrary functions in shared libraries. The repo references sample implementations for basic, forth and lox (all forked from other peoples work). Here's a basic sample
10 def xfn msgbox("user32.dll|MessageBoxA|ptr,cstr,cstr,u32|i32|")
20 print "Showing a Yes/No dialog..."
30 let result = fn msgbox(0, "Do you like dyncall?", "dyncall BASIC demo", 4)
40 if result = 6 then print "You clicked Yes!"
50 if result = 7 then print "You clicked No!"
60 print "MessageBoxA returned "; result
the 'def xfn' is an extension I added to the basic to define external functions. This calls into dyncall, the later msgbox call uses dyncall to push the arguments and perform the function call.
lox playing sounds
// Sound demo using mciSendStringA via dyncall
// mciSendStringA(cmd, retbuf, retbuflen, hwnd) -> u32var mci = exfun("winmm.dll|mciSendStringA|cstr,ptr,u32,ptr|u32|coerce");
print "Playing 4 sounds...";
mci("open C:/Windows/Media/tada.wav type waveaudio alias snd", nil, 0, nil);
mci("play snd wait", nil, 0, nil);
mci("close snd", nil, 0, nil);
same demo in forth
\ Sound demo using mciSendStringA via dyncall
\ mciSendStringA(cmd: cstr, retbuf: ptr, retbuflen: u32, hwnd: ptr) -> u32extern: mci "winmm.dll|mciSendStringA|cstr,ptr,u32,ptr|u32|coerce"
\ Helper: send an MCI command and drop the return value
: mci-cmd ( str -- )
0 0 0 mci drop ;." Playing 4 sounds..." cr
zstring" open C:/Windows/Media/tada.wav type waveaudio alias snd" mci-cmd
zstring" play snd wait" mci-cmd
zstring" close snd" mci-cmd
works on windows , mac, linux. All example so far are windows, heres a linux example
10 REM Standard stream example - Linux/macOS version
20 REM Use fopen("/dev/stderr", "w") to get a FILE* for a standard stream.
30 REM /dev/stdin, /dev/stdout, /dev/stderr are always available on Linux and macOS.
40 REM On Linux use libc.so.6; on macOS use libSystem.B.dylib.
50 PRINT "Standard stream example (Linux/macOS)"
60 DEF XFN c_fopen("libc.so.6|fopen|cstr,cstr|ptr|")
70 DEF XFN c_fputs("libc.so.6|fputs|cstr,ptr|i32|")
80 DEF XFN c_fflush("libc.so.6|fflush|ptr|i32|")
90 DEF XFN c_fclose("libc.so.6|fclose|ptr|i32|")
100 REM Open stderr and stdout
110 LET fp_stderr = FN c_fopen("/dev/stderr", "w")
120 LET fp_stdout = FN c_fopen("/dev/stdout", "w")
130 REM fputs to stderr writes directly to the console
140 LET r = FN c_fputs("Hello from BASIC via fputs (stderr)", fp_stderr)
150 PRINT "fputs returned: "; r
160 LET r = FN c_fputs("Result of 6 * 7 = 42", fp_stderr)
170 PRINT "fputs returned: "; r
180 REM fflush stdout to ensure buffered output is written
190 LET r = FN c_fflush(fp_stdout)
200 PRINT "fflush stdout returned: "; r
210 LET r = FN c_fclose(fp_stderr)
220 LET r = FN c_fclose(fp_stdout)
230 PRINT "Done."
240 END
