diff --git a/README b/README index 982fb89..c24e9e2 100644 --- a/README +++ b/README @@ -13,6 +13,7 @@ Or you can copy/symlink libsipc/libsipc-ffi.so to wherever you need. Additional tools can be built by running `make all-ffi' in the libsipc/ directory (or `make utils' in this one). Functions: +;server functions sipc:bind(file) ;; Bind to socket `file'. Returns the socket descriptor on success and nil on fail (the socket must not already exist) sipc:release(socket) ;; Close socket sipc:hook(socket error-callback message-callback) @@ -25,14 +26,35 @@ Functions: ;; (see libsipc/include/sipc.h for more details) ;; available types are: ; :string - Normal string - ; :binary - CFFI pointer to memory (TODO currently unusable) + ; :binary - pointer to memory (see struct pointer in `pointer.lisp') ; :close - A request to close (the message is always NIL for this type) ;; If an error or message callback returns NIL, the listener is stopped (you still have to call sipc:release()). Otherwise, the return is ignored. (sipc:with-bound-socket (socket-name socket-filename) - body) ;; Bind socket from `socket-filename' to new lexical variable `socket-name' and run (progn @body), then relase the socket afterwards. If the socket fails to bind, return nil and do not attempt to execute body. + body) + ;; Bind socket from `socket-filename' to new lexical variable `socket-name' and run (progn @body), then relase the socket afterwards. If the socket fails to bind, return nil and do not attempt to execute body. + ;; Add `:connect' after socket-filename to connect instead of binding. +;client functions + sipc:connect(file) ;; connect to socket `file', returns sd on success, nil on failure. + sipc:send(sd value &ptional type) ;; send `value' to socket `sd' (optionally specify type (see above types), default :string) + ;; :string -- value expected to be a string + ;; :binary --value expected to be `pointer' struct + ;; :close -- value ignored + sipc:send-quick(file value &optional type) ;; send `value' to socket file `file' See `cl-sipc.lisp' for more documentation. +Pointers: + (sipc:make-pointer :memory cffi-pointer :size size) ;; Make from CFFI foreign-pointer with size + (sipc:pointer-free ptr) ;; Free pointer + (sipc:with-pointer (name &optional type cffi-type) value body...) ;; allocate pointer from value with type and lexical name. free after body. + ;; type: + ;; :string -- expects Lisp string + ;; :sequence -- expects list or vector + ;; :single -- expects single value + ;; :infer (defualt) -- infer from value + ;; optionally specify cffi type (default :unsigned-char) +(see pointer.lisp for more info) + --- Other installation options @@ -70,8 +92,6 @@ Terminal 1: --- -TODO: Implement message sending wrapper. TODO: Internal error handling. TODO: Have libsipc built on system load -TODO: Change :binary message from pointer to vector (or at least pass size to handler so it's usable). TODO: better .so loading diff --git a/ffi.lisp b/ffi.lisp index 9576681..7c57ab3 100644 --- a/ffi.lisp +++ b/ffi.lisp @@ -57,7 +57,7 @@ (data (sif-data message)) (rval (cond ((= type #.+si-string+) (funcall (symbol-value '*on-message*) :string (foreign-string-to-lisp data))) ((= type #.+si-close+) (funcall (symbol-value '*on-message*) :close nil)) - ((= type #.+si-binary+) (funcall (symbol-value '*on-message*) :binary data))))) + ((= type #.+si-binary+) (funcall (symbol-value '*on-message*) :binary (make-pointer :memory data :size size)))))) (if rval 0 1))) diff --git a/pointer.lisp b/pointer.lisp index 8a74987..c97673d 100644 --- a/pointer.lisp +++ b/pointer.lisp @@ -24,6 +24,11 @@ (defmacro with-pointer (desc from &body body) "with pointer allocated desc can have name, type allocated, C type. + available types: + :string -- List string + :sequence -- array from list or vector + :single -- single element + :infer (defualt) -- infer type from value example: (with-pointer (string-ptr) lisp-string body...) @@ -58,6 +63,13 @@ "Free pointer" (foreign-free (pointer-memory ptr))) +(defun pointer-to-array (ptr &optional (type :unsigned-char)) + "pointer to Lisp vector" + (let ((vec (make-array (pointer-size ptr) :initial-element 0))) + (loop for x from 0 below (pointer-size ptr) + do (setf (aref vec x) (mem-aref (pointer-memory ptr) type x))) + vec)) + (mapc #'export '( make-pointer pointer pointer-memory @@ -68,4 +80,5 @@ pointer-from-seq pointer-from with-pointer + pointer-to-array pointer-free)) diff --git a/test-server.lisp b/test-server.lisp index 1f70a63..4262844 100644 --- a/test-server.lisp +++ b/test-server.lisp @@ -17,7 +17,9 @@ (format t "Error: ~a~%" err) nil) ;;returning NIL to the listener stops #'(lambda (type message) ;; Callback ran when a message is received - (format t " <- (~a) ~a~%" type message) ;;print the message & type + (if (eql type :binary) + (format t " <- (~a) ~a (size: ~a)~%" type (sipc:pointer-to-array message) (sipc:pointer-size message)) ;;print the binary message as an array of bytes, the type, & the size + (format t " <- (~a) ~a~%" type message)) ;;print the message & type (not (eql :close type)))))) ;;returning NIL if the type is :CLOSE to stop the listener (format t "[-] listen rc ~a~%" rc) (cl-sipc:release *socket*)) ;;finally, release the socket