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:
parent
702b21f920
commit
bec3f8c289
7 changed files with 159 additions and 36 deletions
12
test/qr.cob
12
test/qr.cob
|
|
@ -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
|
||||
|
|
|
|||
33
test/qr.d
33
test/qr.d
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
21
test/qr.f90
21
test/qr.f90
|
|
@ -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
|
||||
|
|
|
|||
25
test/qr.fs
25
test/qr.fs
|
|
@ -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"
|
||||
|
|
|
|||
46
test/qr.hs
46
test/qr.hs
|
|
@ -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
|
||||
|
|
|
|||
29
test/qr.ml
29
test/qr.ml
|
|
@ -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;;
|
||||
|
|
|
|||
29
test/qr.nim
29
test/qr.nim
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue