1
0
mirror of https://github.com/janet-lang/janet synced 2025-08-06 05:53:49 +00:00

Add :lazy option for ffi/context for jpm quickbin usage.

This commit is contained in:
Calvin Rose 2022-06-13 21:26:03 -05:00
parent 105ba5e124
commit 80729353c8
2 changed files with 55 additions and 16 deletions

View File

@ -1,4 +1,8 @@
(ffi/context "/usr/lib/libgtk-3.so") # :lazy true needed for jpm quickbin
# lazily loads library on first function use
# so the `main` function
# can be marshalled.
(ffi/context "/usr/lib/libgtk-3.so" :lazy true)
(ffi/defbind (ffi/defbind
gtk-application-new :ptr gtk-application-new :ptr
@ -33,13 +37,13 @@
gtk-button-set-label :void gtk-button-set-label :void
[a :ptr b :ptr]) [a :ptr b :ptr])
(def cb (ffi/trampoline :default)) (def cb (delay (ffi/trampoline :default)))
(defn on-active (defn on-active
[app] [app]
(def window (gtk-application-window-new app)) (def window (gtk-application-window-new app))
(def btn (gtk-button-new-with-label "Click Me!")) (def btn (gtk-button-new-with-label "Click Me!"))
(g-signal-connect-data btn "clicked" cb (g-signal-connect-data btn "clicked" (cb)
(fn [btn] (gtk-button-set-label btn "Hello World")) (fn [btn] (gtk-button-set-label btn "Hello World"))
nil 1) nil 1)
(gtk-container-add window btn) (gtk-container-add window btn)
@ -48,5 +52,5 @@
(defn main (defn main
[&] [&]
(def app (gtk-application-new "org.janet-lang.example.HelloApp" 0)) (def app (gtk-application-new "org.janet-lang.example.HelloApp" 0))
(g-signal-connect-data app "activate" cb on-active nil 1) (g-signal-connect-data app "activate" (cb) on-active nil 1)
(g-application-run app 0 nil)) (g-application-run app 0 nil))

View File

@ -3614,9 +3614,26 @@
### ###
### ###
(defmacro delay
"Lazily evaluate a series of expressions. Returns a function that
returns the result of the last expression. Will only evaluate the
body once, and then memoizes the result."
[& forms]
(def state (gensym))
(def loaded (gensym))
~((fn []
(var ,state nil)
(var ,loaded nil)
(fn []
(if ,loaded
,state
(do
(set ,loaded true)
(set ,state (do ,;forms))))))))
(compwhen (dyn 'ffi/native) (compwhen (dyn 'ffi/native)
(defdyn *ffi-context*" Current native library for ffi/bind and other settings") (defdyn *ffi-context* " Current native library for ffi/bind and other settings")
(defn- default-mangle (defn- default-mangle
[name &] [name &]
@ -3625,12 +3642,16 @@
(defn ffi/context (defn ffi/context
"Set the path of the dynamic library to implictly bind, as well "Set the path of the dynamic library to implictly bind, as well
as other global state for ease of creating native bindings." as other global state for ease of creating native bindings."
[native-path &named map-symbols] [native-path &named map-symbols lazy]
(def lib (ffi/native native-path))
(default map-symbols default-mangle) (default map-symbols default-mangle)
(def lib (if lazy nil (ffi/native native-path)))
(def lazy-lib (if lazy (delay (ffi/native native-path))))
(setdyn *ffi-context* (setdyn *ffi-context*
{:native lib @{:native-path native-path
:map-symbols map-symbols})) :native lib
:native-lazy lazy-lib
:lazy lazy
:map-symbols map-symbols}))
(defmacro ffi/defbind (defmacro ffi/defbind
"Generate bindings for native functions in a convenient manner." "Generate bindings for native functions in a convenient manner."
@ -3639,14 +3660,28 @@
(def arg-pairs (partition 2 (last body))) (def arg-pairs (partition 2 (last body)))
(def formal-args (map 0 arg-pairs)) (def formal-args (map 0 arg-pairs))
(def type-args (map 1 arg-pairs)) (def type-args (map 1 arg-pairs))
(def ctx (dyn *ffi-context*))
(def raw-symbol ((get ctx :map-symbols default-mangle) name))
(def ffi-mod (get ctx :native))
(def ptr (assert (ffi/lookup ffi-mod raw-symbol) "failed to find symbol"))
(def computed-type-args (eval ~[,;type-args])) (def computed-type-args (eval ~[,;type-args]))
(def sig (ffi/signature :default ret-type ;computed-type-args)) (def {:native lib
~(defn ,name ,;meta [,;formal-args] :native-path np
(,ffi/call ,ptr ,sig ,;formal-args)))) :lazy lazy
:native-lazy llib
:map-symbols ms} (assert (dyn *ffi-context*) "no ffi context found"))
(def raw-symbol (ms name))
(if lazy
(let [ptr
(delay
(assert (ffi/lookup (llib) raw-symbol) "failed to find symbol"))
sig
(delay
(ffi/signature :default ret-type ;computed-type-args))]
~(defn ,name ,;meta [,;formal-args]
(,ffi/call (,ptr) (,sig) ,;formal-args)))
(let [ptr
(assert (ffi/lookup lib raw-symbol) "failed to find symbol")
sig
(ffi/signature :default ret-type ;computed-type-args)]
~(defn ,name ,;meta [,;formal-args]
(,ffi/call ,ptr ,sig ,;formal-args))))))
### ###
### ###