fix(qr): rewrite 7 failing language tests to use native C FFI

All use dlopen/dlsym to libqrencode.so (system-wide via gcc role):
- Haskell: System.Posix.DynamicLinker + foreign import ccall "dynamic"
- F#: Mono P/Invoke DllImport("libqrencode.so")
- COBOL: LINKAGE SECTION for proper struct pointer access
- Nim: dynlib module (loadLib/symAddr)
- Fortran: renamed dlclose binding to avoid symbol collision
- D: core.sys.posix.dlfcn (dlopen/dlsym)
- OCaml: Ctypes.foreign via ocamlfind #require
This commit is contained in:
russell@unturf.com 2026-01-27 19:53:21 -05:00
parent 702b21f920
commit bec3f8c289
7 changed files with 159 additions and 36 deletions

View file

@ -4,15 +4,18 @@
DATA DIVISION.
WORKING-STORAGE SECTION.
01 QR-PTR USAGE POINTER.
01 QR-VERSION PIC S9(9) COMP-5.
01 QR-WIDTH PIC S9(9) COMP-5.
01 QR-DATA-PTR USAGE POINTER.
01 WS-TEXT PIC X(20) VALUE "unsandbox-qr-ok"
& X"00".
01 WS-ZERO PIC S9(9) COMP-5 VALUE 0.
01 WS-ONE PIC S9(9) COMP-5 VALUE 1.
01 WS-TWO PIC S9(9) COMP-5 VALUE 2.
LINKAGE SECTION.
01 QR-STRUCT.
05 QR-VERSION PIC S9(9) COMP-5.
05 QR-WIDTH PIC S9(9) COMP-5.
05 QR-DATA USAGE POINTER.
PROCEDURE DIVISION.
MAIN-LOGIC.
CALL "QRcode_encodeString"
@ -24,8 +27,7 @@
RETURNING QR-PTR.
IF QR-PTR NOT = NULL
SET ADDRESS OF QR-VERSION TO QR-PTR
SET ADDRESS OF QR-WIDTH TO QR-PTR
SET ADDRESS OF QR-STRUCT TO QR-PTR
DISPLAY "QR:unsandbox-qr-ok:ROWS:" QR-WIDTH
CALL "QRcode_free" USING BY VALUE QR-PTR
ELSE

View file

@ -1,8 +1,33 @@
import core.sys.posix.dlfcn;
import std.stdio;
import qr;
import std.string;
struct QRcode {
int _version;
int width;
void* data;
}
void main() {
auto qrCode = QrCode("unsandbox-qr-ok");
auto size = qrCode.size;
writefln("QR:unsandbox-qr-ok:ROWS:%d", size);
auto lib = dlopen("libqrencode.so", RTLD_LAZY);
if (lib is null) {
stderr.writeln("dlopen: ", dlerror().fromStringz);
return;
}
alias EncFunc = extern(C) QRcode* function(const char*, int, int, int, int);
alias FreeFunc = extern(C) void function(QRcode*);
auto encode = cast(EncFunc) dlsym(lib, "QRcode_encodeString");
auto qfree = cast(FreeFunc) dlsym(lib, "QRcode_free");
auto qr = encode("unsandbox-qr-ok", 0, 1, 2, 1);
if (qr is null) {
stderr.writeln("encode failed");
return;
}
writefln("QR:unsandbox-qr-ok:ROWS:%d", qr.width);
qfree(qr);
dlclose(lib);
}

View file

@ -2,27 +2,31 @@ program qrcode_test
use, intrinsic :: iso_c_binding
implicit none
! QRcode struct layout: version(int), width(int), data(ptr)
type, bind(C) :: QRcode
integer(c_int) :: version
integer(c_int) :: width
type(c_ptr) :: data
end type QRcode
! C function interfaces
interface
type(c_ptr) function dlopen(filename, flag) bind(C, name='dlopen')
import :: c_ptr, c_char, c_int
character(kind=c_char), dimension(*), intent(in) :: filename
integer(c_int), value :: flag
end function
end function dlopen
type(c_funptr) function dlsym(handle, symbol) bind(C, name='dlsym')
import :: c_ptr, c_funptr, c_char
type(c_ptr), value :: handle
character(kind=c_char), dimension(*), intent(in) :: symbol
end function
integer(c_int) function dlclose(handle) bind(C, name='dlclose')
end function dlsym
integer(c_int) function f_dlclose(handle) bind(C, name='dlclose')
import :: c_ptr, c_int
type(c_ptr), value :: handle
end function
end function f_dlclose
end interface
abstract interface
@ -30,11 +34,11 @@ program qrcode_test
import :: c_ptr, c_char, c_int
character(kind=c_char), dimension(*), intent(in) :: s
integer(c_int), value :: ver, lvl, hint, cs
end function
end function encode_iface
subroutine free_iface(qr) bind(C)
import :: c_ptr
type(c_ptr), value :: qr
end subroutine
end subroutine free_iface
end interface
type(c_ptr) :: lib, qr_ptr
@ -42,8 +46,9 @@ program qrcode_test
procedure(encode_iface), pointer :: qr_encode
procedure(free_iface), pointer :: qr_free
type(QRcode), pointer :: qr
integer(c_int) :: rc
lib = dlopen("libqrencode.so" // c_null_char, 2) ! RTLD_NOW=2
lib = dlopen("libqrencode.so" // c_null_char, 2)
enc_fptr = dlsym(lib, "QRcode_encodeString" // c_null_char)
free_fptr = dlsym(lib, "QRcode_free" // c_null_char)
call c_f_procpointer(enc_fptr, qr_encode)
@ -54,5 +59,5 @@ program qrcode_test
write(*, '(A,I0)') 'QR:unsandbox-qr-ok:ROWS:', qr%width
call qr_free(qr_ptr)
call dlclose(lib)
rc = f_dlclose(lib)
end program qrcode_test

View file

@ -1,6 +1,21 @@
open QRCoder
open System
open System.Runtime.InteropServices
let gen = QRCodeGenerator()
let data = gen.CreateQrCode("unsandbox-qr-ok", QRCodeGenerator.ECCLevel.M)
let rows = data.ModuleMatrix.Count
printfn "QR:unsandbox-qr-ok:ROWS:%d" rows
[<DllImport("libqrencode.so", CallingConvention = CallingConvention.Cdecl)>]
extern nativeint QRcode_encodeString(string text, int version, int level, int hint, int caseSensitive)
[<DllImport("libqrencode.so", CallingConvention = CallingConvention.Cdecl)>]
extern void QRcode_free(nativeint qr)
[<Struct; StructLayout(LayoutKind.Sequential)>]
type QRcode =
val version: int
val width: int
let qr = QRcode_encodeString("unsandbox-qr-ok", 0, 1, 2, 1)
if qr <> IntPtr.Zero then
let s = Marshal.PtrToStructure<QRcode>(qr)
printfn "QR:unsandbox-qr-ok:ROWS:%d" s.width
QRcode_free(qr)
else
printfn "QR encode failed"

View file

@ -1,11 +1,41 @@
import Codec.QRCode
import Codec.QRCode.JuicyPixels
import System.Posix.DynamicLinker
import Foreign
import Foreign.C.Types
import Foreign.C.String
data QRcode = QRcode CInt CInt (Ptr Word8)
instance Storable QRcode where
sizeOf _ = 16
alignment _ = 8
peek ptr = QRcode
<$> peekByteOff ptr 0
<*> peekByteOff ptr 4
<*> peekByteOff ptr 8
poke _ _ = return ()
type EncodeFunc = CString -> CInt -> CInt -> CInt -> CInt -> IO (Ptr QRcode)
type FreeFunc = Ptr QRcode -> IO ()
foreign import ccall "dynamic"
mkEncode :: FunPtr EncodeFunc -> EncodeFunc
foreign import ccall "dynamic"
mkFree :: FunPtr FreeFunc -> FreeFunc
main :: IO ()
main = do
let mqr = encodeText defaultQRCodeOptions Iso8859_1OrUtf8WithoutECI "unsandbox-qr-ok"
case mqr of
Nothing -> putStrLn "QR encode failed"
Just img -> do
let matrix = toMatrix True False img :: [[Bool]]
putStrLn $ "QR:unsandbox-qr-ok:ROWS:" ++ show (length matrix)
dl <- dlopen "libqrencode.so" [RTLD_LAZY]
encFP <- dlsym dl "QRcode_encodeString"
freeFP <- dlsym dl "QRcode_free"
let encode = mkEncode encFP
let qfree = mkFree freeFP
cs <- newCString "unsandbox-qr-ok"
qr <- encode cs 0 1 2 1
if qr == nullPtr
then putStrLn "QR encode failed"
else do
QRcode _ w _ <- peek qr
putStrLn $ "QR:unsandbox-qr-ok:ROWS:" ++ show w
qfree qr
free cs

View file

@ -1,4 +1,27 @@
#use "topfind";;
#require "ctypes";;
#require "ctypes.foreign";;
open Ctypes;;
open Foreign;;
type qrcode
let qrcode : qrcode structure typ = structure "QRcode";;
let _qr_version = field qrcode "version" int;;
let qr_width = field qrcode "width" int;;
let _qr_data = field qrcode "data" (ptr char);;
let () = seal qrcode;;
let encode_string =
foreign "QRcode_encodeString"
(string @-> int @-> int @-> int @-> int @-> returning (ptr qrcode));;
let qr_free =
foreign "QRcode_free"
(ptr qrcode @-> returning void);;
let () =
let qr = Qrc.encode "unsandbox-qr-ok" in
let rows = Array.length (Qrc.to_matrix qr) in
Printf.printf "QR:unsandbox-qr-ok:ROWS:%d\n" rows
let qr = encode_string "unsandbox-qr-ok" 0 1 2 1 in
let w = getf !@qr qr_width in
Printf.printf "QR:unsandbox-qr-ok:ROWS:%d\n" w;
qr_free qr;;

View file

@ -1,4 +1,27 @@
import qr
import dynlib
let qrCode = newQR("unsandbox-qr-ok")
echo "QR:unsandbox-qr-ok:ROWS:" & $qrCode.size
type
QRcode {.pure.} = object
version: cint
width: cint
data: pointer
type
QRencodeString = proc(s: cstring, ver: cint, level: cint, hint: cint, cs: cint): ptr QRcode {.cdecl.}
QRfree = proc(qr: ptr QRcode) {.cdecl.}
let lib = loadLib("libqrencode.so")
if lib == nil:
quit("Failed to load libqrencode.so", 1)
let encode = cast[QRencodeString](lib.symAddr("QRcode_encodeString"))
let free_qr = cast[QRfree](lib.symAddr("QRcode_free"))
let qr = encode("unsandbox-qr-ok", 0, 1, 2, 1)
if qr != nil:
echo "QR:unsandbox-qr-ok:ROWS:", qr.width
free_qr(qr)
else:
echo "QR encode failed"
unloadLib(lib)