Hi, CFFI Developers
I'm sorry to point this again. LispWorks 5.0 already support long-long foreign type, but their FOREIGN-TYPED-AREF doesn't support 64bit yet. So a patch is necessary, like attach.
Thanks.
#! /bin/sh /usr/share/dpatch/dpatch-run ## 10_lispworks.dpatch by binghe@localhost.localdomain ## ## All lines beginning with `## DP:' are a description of the patch. ## DP: No description.
@DPATCH@ diff -urNad cffi-20070901~/src/cffi-lispworks.lisp cffi-20070901/src/cffi-lispworks.lisp --- cffi-20070901~/src/cffi-lispworks.lisp 2007-09-22 16:19:19.000000000 +0800 +++ cffi-20070901/src/cffi-lispworks.lisp 2007-09-22 16:20:03.000000000 +0800 @@ -65,12 +65,14 @@ (eval-when (:compile-toplevel :load-toplevel :execute) (mapc (lambda (feature) (pushnew feature *features*)) '(;; Backend mis-features. + #-lispworks5 cffi-features:no-long-long ;; OS/CPU features. #+darwin cffi-features:darwin #+unix cffi-features:unix #+win32 cffi-features:windows #+harp::pc386 cffi-features:x86 + #+harp::amd64 cffi-features:x86-64 #+harp::powerpc cffi-features:ppc32 )))
@@ -163,6 +165,10 @@ (:unsigned-int '(:unsigned :int)) (:long :long) (:unsigned-long '(:unsigned :long)) + #+lispworks5 + (:long-long '(:long :long)) + #+lispworks5 + (:unsigned-long-long '(:unsigned :long :long)) (:float :float) (:double :double) (:pointer :pointer) @@ -170,7 +176,7 @@
;;; Convert a CFFI type keyword to a symbol suitable for passing to ;;; FLI:FOREIGN-TYPED-AREF. -#+#.(cl:if (cl:find-symbol "FOREIGN-TYPED-AREF" "FLI") '(and) '(or)) +#+#.(cl:if (cl:find-symbol "FOREIGN-TYPED-AREF" "FLI") '(and lispworks-32bit) '(or)) (defun convert-foreign-typed-aref-type (cffi-type) (ecase cffi-type ((:char :short :int :long) @@ -188,7 +194,7 @@
;;; In LispWorks versions where FLI:FOREIGN-TYPED-AREF is fbound, use ;;; it instead of FLI:DEREFERENCE in the optimizer for %MEM-REF. -#+#.(cl:if (cl:find-symbol "FOREIGN-TYPED-AREF" "FLI") '(and) '(or)) +#+#.(cl:if (cl:find-symbol "FOREIGN-TYPED-AREF" "FLI") '(and lispworks-32bit) '(or)) (define-compiler-macro %mem-ref (&whole form ptr type &optional (off 0)) (if (constantp type) (let ((type (eval type))) @@ -204,7 +210,7 @@
;;; Open-code the call to FLI:DEREFERENCE when TYPE is constant at ;;; macroexpansion time, when FLI:FOREIGN-TYPED-AREF is not available. -#-#.(cl:if (cl:find-symbol "FOREIGN-TYPED-AREF" "FLI") '(and) '(or)) +#-#.(cl:if (cl:find-symbol "FOREIGN-TYPED-AREF" "FLI") '(and lispworks-32bit) '(or)) (define-compiler-macro %mem-ref (&whole form ptr type &optional (off 0)) (if (constantp type) (let ((ptr-form (if (eql off 0) ptr `(inc-pointer ,ptr ,off))) @@ -220,7 +226,7 @@
;;; In LispWorks versions where FLI:FOREIGN-TYPED-AREF is fbound, use ;;; it instead of FLI:DEREFERENCE in the optimizer for %MEM-SET. -#+#.(cl:if (cl:find-symbol "FOREIGN-TYPED-AREF" "FLI") '(and) '(or)) +#+#.(cl:if (cl:find-symbol "FOREIGN-TYPED-AREF" "FLI") '(and lispworks-32bit) '(or)) (define-compiler-macro %mem-set (&whole form val ptr type &optional (off 0)) (if (constantp type) (once-only (val) @@ -239,7 +245,7 @@
;;; Open-code the call to (SETF FLI:DEREFERENCE) when TYPE is constant ;;; at macroexpansion time. -#-#.(cl:if (cl:find-symbol "FOREIGN-TYPED-AREF" "FLI") '(and) '(or)) +#-#.(cl:if (cl:find-symbol "FOREIGN-TYPED-AREF" "FLI") '(and lispworks-32bit) '(or)) (define-compiler-macro %mem-set (&whole form val ptr type &optional (off 0)) (if (constantp type) (once-only (val)
Hello Tian,
On 22/09/2007, Chun Tian (binghe) binghe.lisp@gmail.com wrote:
#-lispworks5 cffi-features:no-long-long
If possible, we should instead use one of the following approaches for checking whether Lispworks has long long support:
* some feature keyword symbol specific to long long support, if Lispworks provides any.
* check for version 5.0 or higher, presuming all platforms support long long as of version 5.0. (does Lispworks provide something like Allegro's :VERSION>=?)
* programmatically check for long long support at read-time, i.e.: (eval-when (<always>) (unless (somehow-check-for-long-long-here) (pushnew 'cffi-features:no-long-long *features*)))
If you could modify the patch to use one of these alternative approaches, that would be great. Thanks.
Luís Oliveira wrote:
Hello Tian,
On 22/09/2007, Chun Tian (binghe) binghe.lisp@gmail.com wrote:
-+ #-lispworks5 cffi-features:no-long-long
If possible, we should instead use one of the following approaches for checking whether Lispworks has long long support:
some feature keyword symbol specific to long long support, if Lispworks provides any.
check for version 5.0 or higher, presuming all platforms support long long as of version 5.0. (does Lispworks provide something like Allegro's :VERSION>=?)
programmatically check for long long support at read-time, i.e.: (eval-when (<always>) (unless (somehow-check-for-long-long-here) (pushnew 'cffi-features:no-long-long *features*)))
If you could modify the patch to use one of these alternative approaches, that would be great. Thanks.
You're right and I was wrong:
1. It seems that only 64bit LispWorks 5.0 has long-long support, not 32bit, and it's undocumented. 2. the feature :lispworks-32bit does not exist in versions prior to 5.0, so I cannot use it to detect FOREIGN-TYPED-AREF.
The long-long support maybe detect using (fli::64bit-long-p), I found this function in both 4.4 and 5.0 version of lispworks. So I think maybe these #+lispworks5 and #-lispworks5 can be replaced with #+#.(cl:if (fli::64bit-long-p) '(and) '(or)), etc.
Another problem is that LispWorks's FOREIGN-TYPED-AREF cannot accept the type | (unsigned-byte 64)| and |(signed-byte 64) now, though people from LispWorks, Ltd say they will support this in next version. It's quite hard for me to give a patch which can still use other type on |FOREIGN-TYPED-AREF on platform support long-long, and this patch should also consider the future version of lispworks which can support | (unsigned-byte 64)| and |(signed-byte 64).
And, I think |Lispworks didn't provide something like Allegro's :VERSION>=?), but seems LispWorks put its version in *features*, and LispWorks's version change is much small than Allegro, so the same detect maybe done with combined #+.
If Martin Simmons see this post, I hope he can give us a better answer. | Thanks.
|Chun Tian (binghe)
On Sat, 22 Sep 2007 21:57:13 +0800, Chun Tian (binghe) said:
Luís Oliveira wrote:
Hello Tian,
On 22/09/2007, Chun Tian (binghe) binghe.lisp@gmail.com wrote:
-+ #-lispworks5 cffi-features:no-long-long
If possible, we should instead use one of the following approaches for checking whether Lispworks has long long support:
some feature keyword symbol specific to long long support, if Lispworks provides any.
check for version 5.0 or higher, presuming all platforms support long long as of version 5.0. (does Lispworks provide something like Allegro's :VERSION>=?)
programmatically check for long long support at read-time, i.e.: (eval-when (<always>) (unless (somehow-check-for-long-long-here) (pushnew 'cffi-features:no-long-long *features*)))
If you could modify the patch to use one of these alternative approaches, that would be great. Thanks.
You're right and I was wrong:
- It seems that only 64bit LispWorks 5.0 has long-long support, not
32bit, and it's undocumented. 2. the feature :lispworks-32bit does not exist in versions prior to 5.0, so I cannot use it to detect FOREIGN-TYPED-AREF.
The long-long support maybe detect using (fli::64bit-long-p), I found this function in both 4.4 and 5.0 version of lispworks. So I think maybe these #+lispworks5 and #-lispworks5 can be replaced with #+#.(cl:if (fli::64bit-long-p) '(and) '(or)), etc.
Another problem is that LispWorks's FOREIGN-TYPED-AREF cannot accept the type | (unsigned-byte 64)| and |(signed-byte 64) now, though people from LispWorks, Ltd say they will support this in next version. It's quite hard for me to give a patch which can still use other type on |FOREIGN-TYPED-AREF on platform support long-long, and this patch should also consider the future version of lispworks which can support | (unsigned-byte 64)| and |(signed-byte 64).
And, I think |Lispworks didn't provide something like Allegro's :VERSION>=?), but seems LispWorks put its version in *features*, and LispWorks's version change is much small than Allegro, so the same detect maybe done with combined #+.
If Martin Simmons see this post, I hope he can give us a better answer.
Testing FLI::64BIT-LONG-P is not right -- it is false on Windows x64, but that platform fully supports :long-long.
Support for :long-long is available in the LispWorks 5.0 FLI: - On all 64-bit platforms. - For FLI:DEFINE-FOREIGN-FUNCTION on all 32-bit platforms.
It is not avaliable in: - LispWorks 4. - For data access functions such as FLI:DEREFERENCE on 32-bit platforms.
Because of this last restriction, if CFFI wants to support :long-long on 32-bit LispWorks platforms, then it can do it for DEFCFUN but not other APIs. A single cffi-feature is not enough to describe this, so it could just support it on 64-bit platforms by using #-lispworks-64bit to enable cffi-features:no-long-long.
To avoid the bugs in FOREIGN-TYPED-AREF, I suggest something like this for the optimizers (untested):
#+#.(cl:if (cl:find-symbol "FOREIGN-TYPED-AREF" "FLI") '(and) '(or)) (define-compiler-macro %mem-ref (&whole form ptr type &optional (off 0)) (if (constantp type) (let ((type (eval type))) (if (or (eql type :pointer) #+(and :lispworks-64bit :lispworks5.0) (member type '(:long :unsigned-long :long-long :unsigned-long-long))) (let ((fli-type (convert-foreign-type type)) (ptr-form (if (eql off 0) ptr `(inc-pointer ,ptr ,off)))) `(fli:dereference ,ptr-form :type ',fli-type)) (let ((lisp-type (convert-foreign-typed-aref-type type))) `(locally (declare (optimize (speed 3) (safety 0))) (fli:foreign-typed-aref ',lisp-type ,ptr (the fixnum ,off)))))) form))
Hope that helps.
Thanks for your tips Martin.
On 24/09/2007, Martin Simmons martin@lispworks.com wrote:
Because of this last restriction, if CFFI wants to support :long-long on 32-bit LispWorks platforms, then it can do it for DEFCFUN but not other APIs. A single cffi-feature is not enough to describe this, so it could just support it on 64-bit platforms by using #-lispworks-64bit to enable cffi-features:no-long-long.
Tian, since I don't have access to 64-bit lispworks I guess you're on your own. If you come up with a patch, though, I'll gladly test it on 32-bit lispworks and apply it.
Thanks again to Martin Simmons.
Luís Oliveira wrote:
Thanks for your tips Martin.
On 24/09/2007, Martin Simmons martin@lispworks.com wrote:
Because of this last restriction, if CFFI wants to support :long-long on 32-bit LispWorks platforms, then it can do it for DEFCFUN but not other APIs. A single cffi-feature is not enough to describe this, so it could just support it on 64-bit platforms by using #-lispworks-64bit to enable cffi-features:no-long-long.
Tian, since I don't have access to 64-bit lispworks I guess you're on your own. If you come up with a patch, though, I'll gladly test it on 32-bit lispworks and apply it.
Oliveira,
As Martin Simmons' suggest, I made another patch which works for me on my 64-bit lispworks edition. Please review it and apply it as your wish, thanks.
Chun Tian (binghe)
#! /bin/sh /usr/share/dpatch/dpatch-run ## 10_lispworks.dpatch by binghe@localhost.localdomain ## ## All lines beginning with `## DP:' are a description of the patch. ## DP: No description.
@DPATCH@ diff -urNad cffi-20070901~/src/cffi-lispworks.lisp cffi-20070901/src/cffi-lispworks.lisp --- cffi-20070901~/src/cffi-lispworks.lisp 2007-09-25 13:01:10.000000000 +0800 +++ cffi-20070901/src/cffi-lispworks.lisp 2007-09-25 13:21:52.000000000 +0800 @@ -65,12 +65,14 @@ (eval-when (:compile-toplevel :load-toplevel :execute) (mapc (lambda (feature) (pushnew feature *features*)) '(;; Backend mis-features. + #-lispworks-64bit cffi-features:no-long-long ;; OS/CPU features. #+darwin cffi-features:darwin #+unix cffi-features:unix #+win32 cffi-features:windows #+harp::pc386 cffi-features:x86 + #+harp::amd64 cffi-features:x86-64 #+harp::powerpc cffi-features:ppc32 )))
@@ -163,6 +165,10 @@ (:unsigned-int '(:unsigned :int)) (:long :long) (:unsigned-long '(:unsigned :long)) + #+lispworks-64bit + (:long-long '(:long :long)) + #+lispworks-64bit + (:unsigned-long-long '(:unsigned :long :long)) (:float :float) (:double :double) (:pointer :pointer) @@ -173,9 +179,10 @@ #+#.(cl:if (cl:find-symbol "FOREIGN-TYPED-AREF" "FLI") '(and) '(or)) (defun convert-foreign-typed-aref-type (cffi-type) (ecase cffi-type - ((:char :short :int :long) + ((:char :short :int :long #+lispworks-64bit :long-long) `(signed-byte ,(* 8 (%foreign-type-size cffi-type)))) - ((:unsigned-char :unsigned-short :unsigned-int :unsigned-long) + ((:unsigned-char :unsigned-short :unsigned-int :unsigned-long + #+lispworks-64bit :unsigned-long-long) `(unsigned-byte ,(* 8 (%foreign-type-size cffi-type)))) (:float 'single-float) (:double 'double-float))) @@ -192,7 +199,10 @@ (define-compiler-macro %mem-ref (&whole form ptr type &optional (off 0)) (if (constantp type) (let ((type (eval type))) - (if (eql type :pointer) + (if (or (eql type :pointer) + #+(and lispworks-64bit lispworks5.0) + (member type '(:long :unsigned-long + :long-long :unsigned-long-long))) (let ((fli-type (convert-foreign-type type)) (ptr-form (if (eql off 0) ptr `(inc-pointer ,ptr ,off)))) `(fli:dereference ,ptr-form :type ',fli-type)) @@ -225,7 +235,10 @@ (if (constantp type) (once-only (val) (let ((type (eval type))) - (if (eql type :pointer) + (if (or (eql type :pointer) + #+(and lispworks-64bit lispworks5.0) + (member type '(:long :unsigned-long + :long-long :unsigned-long-long))) (let ((fli-type (convert-foreign-type type)) (ptr-form (if (eql off 0) ptr `(inc-pointer ,ptr ,off)))) `(setf (fli:dereference ,ptr-form :type ',fli-type) ,val))
Luís Oliveira wrote:
Hello Tian,
On 22/09/2007, Chun Tian (binghe) binghe.lisp@gmail.com wrote:
#-lispworks5 cffi-features:no-long-long
If possible, we should instead use one of the following approaches for checking whether Lispworks has long long support:
some feature keyword symbol specific to long long support, if Lispworks provides any.
check for version 5.0 or higher, presuming all platforms support long long as of version 5.0. (does Lispworks provide something like Allegro's :VERSION>=?)
programmatically check for long long support at read-time, i.e.: (eval-when (<always>) (unless (somehow-check-for-long-long-here) (pushnew 'cffi-features:no-long-long *features*)))
If you could modify the patch to use one of these alternative approaches, that would be great. Thanks.
Attach is a modified patch which I use now, using (fli::64bit-long-p).
#! /bin/sh /usr/share/dpatch/dpatch-run ## 10_lispworks.dpatch by binghe@localhost.localdomain ## ## All lines beginning with `## DP:' are a description of the patch. ## DP: No description.
@DPATCH@ diff -urNad cffi-20070901~/src/cffi-lispworks.lisp cffi-20070901/src/cffi-lispworks.lisp --- cffi-20070901~/src/cffi-lispworks.lisp 2007-09-22 22:33:06.000000000 +0800 +++ cffi-20070901/src/cffi-lispworks.lisp 2007-09-22 22:35:58.000000000 +0800 @@ -65,12 +65,14 @@ (eval-when (:compile-toplevel :load-toplevel :execute) (mapc (lambda (feature) (pushnew feature *features*)) '(;; Backend mis-features. + #-#.(cl:if (fli::64bit-long-p) '(and) '(or)) cffi-features:no-long-long ;; OS/CPU features. #+darwin cffi-features:darwin #+unix cffi-features:unix #+win32 cffi-features:windows #+harp::pc386 cffi-features:x86 + #+harp::amd64 cffi-features:x86-64 #+harp::powerpc cffi-features:ppc32 )))
@@ -163,6 +165,10 @@ (:unsigned-int '(:unsigned :int)) (:long :long) (:unsigned-long '(:unsigned :long)) + #+#.(cl:if (fli::64bit-long-p) '(and) '(or)) + (:long-long '(:long :long)) + #+#.(cl:if (fli::64bit-long-p) '(and) '(or)) + (:unsigned-long-long '(:unsigned :long :long)) (:float :float) (:double :double) (:pointer :pointer) @@ -170,7 +176,8 @@
;;; Convert a CFFI type keyword to a symbol suitable for passing to ;;; FLI:FOREIGN-TYPED-AREF. -#+#.(cl:if (cl:find-symbol "FOREIGN-TYPED-AREF" "FLI") '(and) '(or)) +#+#.(cl:if (cl:and (cl:find-symbol "FOREIGN-TYPED-AREF" "FLI") + (cl:not (fli::64bit-long-p))) '(and) '(or)) (defun convert-foreign-typed-aref-type (cffi-type) (ecase cffi-type ((:char :short :int :long) @@ -188,7 +195,8 @@
;;; In LispWorks versions where FLI:FOREIGN-TYPED-AREF is fbound, use ;;; it instead of FLI:DEREFERENCE in the optimizer for %MEM-REF. -#+#.(cl:if (cl:find-symbol "FOREIGN-TYPED-AREF" "FLI") '(and) '(or)) +#+#.(cl:if (cl:and (cl:find-symbol "FOREIGN-TYPED-AREF" "FLI") + (cl:not (fli::64bit-long-p))) '(and) '(or)) (define-compiler-macro %mem-ref (&whole form ptr type &optional (off 0)) (if (constantp type) (let ((type (eval type))) @@ -204,7 +212,8 @@
;;; Open-code the call to FLI:DEREFERENCE when TYPE is constant at ;;; macroexpansion time, when FLI:FOREIGN-TYPED-AREF is not available. -#-#.(cl:if (cl:find-symbol "FOREIGN-TYPED-AREF" "FLI") '(and) '(or)) +#-#.(cl:if (cl:and (cl:find-symbol "FOREIGN-TYPED-AREF" "FLI") + (cl:not (fli::64bit-long-p))) '(and) '(or)) (define-compiler-macro %mem-ref (&whole form ptr type &optional (off 0)) (if (constantp type) (let ((ptr-form (if (eql off 0) ptr `(inc-pointer ,ptr ,off))) @@ -220,7 +229,8 @@
;;; In LispWorks versions where FLI:FOREIGN-TYPED-AREF is fbound, use ;;; it instead of FLI:DEREFERENCE in the optimizer for %MEM-SET. -#+#.(cl:if (cl:find-symbol "FOREIGN-TYPED-AREF" "FLI") '(and) '(or)) +#+#.(cl:if (cl:and (cl:find-symbol "FOREIGN-TYPED-AREF" "FLI") + (cl:not (fli::64bit-long-p))) '(and) '(or)) (define-compiler-macro %mem-set (&whole form val ptr type &optional (off 0)) (if (constantp type) (once-only (val) @@ -239,7 +249,8 @@
;;; Open-code the call to (SETF FLI:DEREFERENCE) when TYPE is constant ;;; at macroexpansion time. -#-#.(cl:if (cl:find-symbol "FOREIGN-TYPED-AREF" "FLI") '(and) '(or)) +#-#.(cl:if (cl:and (cl:find-symbol "FOREIGN-TYPED-AREF" "FLI") + (cl:not (fli::64bit-long-p))) '(and) '(or)) (define-compiler-macro %mem-set (&whole form val ptr type &optional (off 0)) (if (constantp type) (once-only (val)