[Openmcl-devel] Gtk "Hello, world" example in OpenMCL

Andrew P. Lentvorski, Jr. bsder at mail.allcaps.org
Sun Aug 8 16:26:42 PDT 2004


Folks,

Here is a sample program which creates a button inside a Gtk window an 
responds to button presses with "Hello, world."  It uses only the 
standard foreign function call interfaces.

Please critique this as I would like to get it added to the 
documentation, but I don't know enough to be able to validate whether I 
am doing things well/correctly.

Thanks,
-a

;; File "hello-gtk.lisp"
;;
;; To execute, do a (load "hello-gtk.lisp) at the mcl prompt.

;; Open required libraries
;; Change this to whatever path is required for your machine

(open-shared-library "/home/devel/lib/libgtk-x11-2.0.0.dylib")


;; Helper functions for heap allocation

;; The ivector functions should be placed into a library

;; make-heap-ivector courtesy of Gary Byers
(defun make-heap-ivector (element-count element-type)
   (let* ((subtag (ccl::element-type-subtype element-type)))
     (unless (= (logand subtag target::fulltagmask)
                target::fulltag-immheader)
       (error "~s is not an ivector subtype." element-type))
     (let* ((size-in-bytes (ccl::subtag-bytes subtag element-count)))
       (ccl::%make-heap-ivector subtag size-in-bytes element-count))))

;; dispose-heap-ivector created for symmetry
(defmacro dispose-heap-ivector (a mp)
   `(progn
      (ccl::%dispose-heap-ivector ,a)
      ;; Demolish the arguments for safety
      (setf ,a nil)
      (setf ,mp nil)))

(defun make-string-ivector (s)
   (let ((slen (length s)))
     (multiple-value-bind (sa sap)
	(make-heap-ivector (+ slen 1) 'character)
       (dotimes (i slen)
	(setf (aref sa i) (aref s i)))
       (setf (aref sa slen) '#\Null)
       (values sa sap))))

(defun gtk-init ()
   ;; Do argc and argv need to be (declare (dynamic-extent argc)) ?

   ;; There has *got* to be a better way to do this
   (multiple-value-bind (argc argc-ptr)
       (make-heap-ivector 1 '(unsigned-byte 32))
     ;; This allocates the character (To be set to null)
     (multiple-value-bind (argv argv-ptr)
	(make-heap-ivector 1 '(unsigned-byte 8))
       ;; This allocates the pointer to the character
       (multiple-value-bind (argvp argvp-ptr)
	  (make-heap-ivector 1 '(unsigned-byte 32))
	;; Set call for no incoming arguments
	(setf (aref argc 0) 0)
	;; Set incoming string to null character
	(setf (aref argv 0) 0)
	;; Set pointer to incoming string
	(setf (aref argvp 0) (ccl::%ptr-to-int argv-ptr))

	;; Finally.  Call the function.
	(external-call "_gtk_init" :address argc-ptr :address argvp-ptr :void)

	;; Check the returns and do something with them if you want

	;; Deallocate memory
	(dispose-heap-ivector argvp argvp-ptr))
       (dispose-heap-ivector argv argv-ptr))
     (dispose-heap-ivector argc argc-ptr)))

(defun gtk-poll ()
   (do* ()
       ((eql (external-call "_gtk_events_pending" :signed-long) 0) nil)
     (external-call "_gtk_main_iteration" :signed-long)))

;; This is an enum from the gtkenums.h file
(setq *gtk-window-toplevel* 0)

(gtk-init)
(setq window (external-call "_gtk_window_new" :signed-int 
*gtk-window-toplevel* :address))

(setq button-label '"Hello")

(multiple-value-bind (la lap)
     (make-string-ivector button-label)
   (setq bla la)
   (setq blap lap))

(setq button (external-call "_gtk_button_new_with_label" :address blap 
:address))

(external-call "_gtk_container_add" :address window :address button 
:void)

(external-call "_gtk_widget_show" :address button :void)
(external-call "_gtk_widget_show" :address window :void)

(defcallback hello-callback (:address widget :address data :void)
   (format t "Hello, world."))

(setq clicked-string '"clicked")

(multiple-value-bind (la lap)
     (make-string-ivector clicked-string)
   (setq clicked-array la)
   (setq clicked-pointer lap))

(setq null (ccl:%int-to-ptr 0))

;; g_signal_connect is a C preprocessor macro so use
;; the underlying "_g_signal_connect_data" call
(external-call "_g_signal_connect_data"
	       :address button :address clicked-pointer
	       :address hello-callback :address null
	       :address null :signed 0 :unsigned)

(ccl::%install-periodic-task 'gtk-task #'gtk-poll 10)




More information about the Openmcl-devel mailing list