[cffi-objects-cvs] r2 -

rklochkov at common-lisp.net rklochkov at common-lisp.net
Mon Feb 20 18:55:21 UTC 2012


Author: rklochkov
Date: Mon Feb 20 10:55:20 2012
New Revision: 2

Log:
Added array with variable length

Added:
   array.lisp
Modified:
   cffi-objects.asd
   freeable.lisp
   package.lisp

Added: array.lisp
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ array.lisp	Mon Feb 20 10:55:20 2012	(r2)
@@ -0,0 +1,62 @@
+;;;
+;;; array.lisp --- array
+;;;
+;;; Copyright (C) 2012, Roman Klochkov <monk at slavsoft.surgut.ru>
+;;;
+
+(in-package #:cffi-objects)
+
+(defvar *array-length* (foreign-alloc :uint))
+
+;; TODO: add with-pointer-to-vector-data optimization
+(define-foreign-type cffi-array (freeable)
+  ((element-type :initarg :type :accessor element-type))
+  (:actual-type :pointer))
+
+(define-parse-method carray (type &key free)
+  (make-instance 'cffi-array :type type :free free))
+
+(defmethod translate-to-foreign (value (cffi-array cffi-array))
+  (if (pointerp value)
+      value
+      (let* ((length (length value))
+             (type (element-type cffi-array))
+             (res (foreign-alloc type :count length)))
+        (dotimes (i length (values res t))
+          (setf (mem-aref res type i) (elt value i)))
+        res)))
+
+(defmethod translate-from-foreign (ptr (cffi-array cffi-array))
+  (let ((array-length (mem-ref *array-length* :uint)))
+    (let* ((res (make-array array-length))
+           (el-type (element-type cffi-array)))
+      (dotimes (i array-length)
+        (setf (aref res i) (mem-aref ptr el-type i)))
+      res)))
+
+(define-foreign-type cffi-null-array (freeable)
+  ((element-type :initarg :type :accessor element-type))
+  (:actual-type :pointer))
+
+(define-parse-method null-array (type &key free)
+  (make-instance 'cffi-null-array :type type :free free))
+
+(defmethod translate-to-foreign (value (cffi-null-array cffi-null-array))
+  (if (pointerp value)
+      value
+      (let* ((length (length value))
+             (type (element-type cffi-null-array))
+             (res (foreign-alloc type :count (+ 1 length))))
+        (dotimes (i length (values res t))
+          (setf (mem-aref res type i) (elt value i)))
+        (setf (mem-aref res :pointer length) (null-pointer))
+        res)))
+
+(defmethod translate-from-foreign (ptr (cffi-null-array cffi-null-array))
+  (let* ((res nil)
+         (el-type (element-type cffi-null-array)))
+    (do ((i 0 (+ i 1))) ((null-pointer-p (mem-aref ptr :pointer i)))
+      (push (mem-aref ptr el-type i) res))
+    (coerce (nreverse res) 'array)))
+
+(defctype string-array (null-array :string) "Zero-terminated string array")
\ No newline at end of file

Modified: cffi-objects.asd
==============================================================================
--- cffi-objects.asd	Thu Feb  9 07:53:55 2012	(r1)
+++ cffi-objects.asd	Mon Feb 20 10:55:20 2012	(r2)
@@ -22,4 +22,5 @@
    (:file object :depends-on (freeable))
    (:file pfunction :depends-on (package))
    (:file setters :depends-on (package))
+   (:file array :depends-on (package))
    (:file struct :depends-on (object setters))))

Modified: freeable.lisp
==============================================================================
--- freeable.lisp	Thu Feb  9 07:53:55 2012	(r1)
+++ freeable.lisp	Mon Feb 20 10:55:20 2012	(r2)
@@ -9,12 +9,14 @@
 
 (define-foreign-type freeable-base ()
   ((free :accessor object-free :initarg :free :initform :no-transfer
-         :type (member :none :all :no-transfer :transfer)
+         :type (member :none :all :no-transfer :transfer :container)
          :documentation "Free returned or sent value.
 :NONE -- no free at all
 :ALL -- free always (after sending to FFI, or after recieved translation)
 :TRANSFER -- client frees, so free after recieve
 :NO-TRANSFER -- host frees, so free after sending to FFI.
+:CONTAINER -- the object is a container, ALL for container and NO-TRANSFER for
+contained items
 You should call FREE-RETURNED-IF-NEEDED and FREE-SENT-IF-NEEDED in
 appropriate places of your CFFI translators")))
 
@@ -32,11 +34,11 @@
     (free-ptr type ptr)))
 
 (defun free-sent-if-needed (type ptr)
-  (when (member (object-free type) '(:all :no-transfer))
+  (when (member (object-free type) '(:all :container :no-transfer))
     (free-sent-ptr type ptr)))
 
 (defun free-returned-if-needed (type ptr)
-  (when (member (object-free type) '(:all :transfer))
+  (when (member (object-free type) '(:all :container :transfer))
     (free-returned-ptr type ptr)))
 
 (defclass freeable (freeable-base) ()

Modified: package.lisp
==============================================================================
--- package.lisp	Thu Feb  9 07:53:55 2012	(r1)
+++ package.lisp	Mon Feb 20 10:55:20 2012	(r2)
@@ -21,18 +21,28 @@
    #:gconstructor
 
    #:object
+   #:find-object
    #:object-by-id
    #:*objects*
    #:*objects-ids*
+   #:object-class
+   #:volatile
    ;; slots
    #:pointer
    ;; methods
    #:free
 
+
+   #:*array-length*
    ;; types
    #:pstring
    #:pfunction
    #:cffi-object
+   #:cffi-array
+   #:cffi-null-array
+   #:carray
+   #:null-array
+   #:string-array
 
    #:struct
 ;   #:cffi-struct




More information about the cffi-objects-cvs mailing list