Hello:
I have a problem with cffi and I don't know if I'm doing something wrong or if It's a bug.
I'm writting a ffi interface to a windowing kit. When testing It I became in problems. The windowing kit has a struct called Rect with the following definition:
struct Rect
{
int x;
int y;
int width;
int height;
};
plus a functional interface to create Rect objects:
Rect app_new_rect(int x , int y , int w , int h ) ;
That function works well because I can run the examples of the toolkit and I see the windows. But when I create the cffi interface, I have problems.
The cffi interface for app_new_rect is:
(cffi:defcstruct Rect
(x :int)
(y :int)
(width :int)
(height :int))
(cffi:defcfun ("app_new_rect" app_new_rect) Rect
(x :int)
(y :int)
(width :int)
(height :int))
The problem is that when I use the Rect object that this function creates, I get segmentation faults. Ex:
CL-USER> (setq r (app_new_rect 0 0 200 300 ) )
#.(SB-SYS:INT-SAP #X00000000)
CL-USER> (with-foreign-slots ( (x y width height ) r Rect )
(list x y width height )
)
Unhandled memory fault at #x0.
[Condition of type SB-SYS:MEMORY-FAULT-ERROR]
Restarts:
0: [ABORT] Return to SLIME's top level.
1: [TERMINATE-THREAD] Terminate this thread (#<THREAD "repl-thread" {1002886941}>)
Backtrace:
0: (SB-SYS:MEMORY-FAULT-ERROR)
1: (SB-SYS:MEMORY-FAULT-ERROR)
2: ("foreign function: call_into_lisp")
3: ("foreign function: post_signal_tramp")
4: (NIL)
5: (SB-INT:SIMPLE-EVAL-IN-LEXENV
(WITH-FOREIGN-SLOTS ((X Y WIDTH HEIGHT) R RECT)
(LIST X Y WIDTH HEIGHT))
#<NULL-LEXENV>)
When I had that problem, I tried to write a Lisp-only function to create Rect objects , to not use app_new_rect at all. I wrote the next function:
(defun rect ( x y width height )
(cffi:with-foreign-object ( ptr 'rect )
(setf (cffi:foreign-slot-value ptr 'rect 'x ) x )
(setf (cffi:foreign-slot-value ptr 'rect 'y ) y )
(setf (cffi:foreign-slot-value ptr 'rect 'width ) width )
(setf (cffi:foreign-slot-value ptr 'rect 'height ) height )
ptr
)
)
But my surprise is that this doesn't set correctly the values of the slots. See the following output from slime:
CL-USER> (setq my-little-rectangle (rect 0 0 200 300 ) )
; in: LAMBDA NIL
; (SETQ MY-LITTLE-RECTANGLE (RECT 0 0 200 300))
;
; caught WARNING:
; undefined variable: MY-LITTLE-RECTANGLE
;
; caught WARNING:
; This variable is undefined:
; MY-LITTLE-RECTANGLE
;
; compilation unit finished
; caught 2 WARNING conditions
#.(SB-SYS:INT-SAP #X2ACC75E76FE8)
CL-USER> (with-foreign-slots ( (x y width height ) my-little-rectangle Rect )
(list x y width height )
)
; in: LAMBDA NIL
; (LET ((#:PTR2816 MY-LITTLE-RECTANGLE))
; (SYMBOL-MACROLET ((X (FOREIGN-SLOT-VALUE #:PTR2816 'RECT 'X))
; (Y (FOREIGN-SLOT-VALUE #:PTR2816 'RECT 'Y))
; (WIDTH (FOREIGN-SLOT-VALUE #:PTR2816 'RECT 'WIDTH))
; (HEIGHT (FOREIGN-SLOT-VALUE #:PTR2816 'RECT 'HEIGHT)))
; (LIST X Y WIDTH HEIGHT)))
;
; caught WARNING:
; undefined variable: MY-LITTLE-RECTANGLE
;
; caught WARNING:
; This variable is undefined:
; MY-LITTLE-RECTANGLE
;
; compilation unit finished
; caught 2 WARNING conditions
(1192261452 0 785098 0)
The output from the last input should be (0 0 200 300) but I get (1192261452 0 785098 0 ). As the Rect object is used for drawing, nothing works for me.
Please, can anyone explain me what I'm doing wrong? I use an AMD64 on OpenSuse 10.1 x86_64, plus sbcl-1.0.9-x86_64 and cffi_0.9.2 . I've tested also the snapshot cffi-070901 and I get the same problem.
Thank you.
On Sat, 13 Oct 2007 11:35:40 +0200 "Felip Alàez Nadal" uu.nix.uu@gmail.com wrote:
Hello:
I have a problem with cffi and I don't know if I'm doing something wrong or if It's a bug.
...
plus a functional interface to create Rect objects:
Rect app_new_rect(int x , int y , int w , int h ) ;
Hi, it looks like this functions returns Rects by value. If section 13 of the CFFI manual is still up-to-date passing structs by value is not supported by CFFI.
When I had that problem, I tried to write a Lisp-only function to create Rect objects , to not use app_new_rect at all. I wrote the next function:
(defun rect ( x y width height )
(cffi:with-foreign-object ( ptr 'rect ) (setf (cffi:foreign-slot-value ptr 'rect 'x ) x ) (setf (cffi:foreign-slot-value ptr 'rect 'y ) y ) (setf (cffi:foreign-slot-value ptr 'rect 'width ) width ) (setf (cffi:foreign-slot-value ptr 'rect 'height ) height ) ptr )
)
The ptr you create in with-foreign-object is only valid in the scope of with-foreign-object, so you shouldn't return it outside like that.
Sincerely, Mikael Lax