Arg!!! - C Interfacing Problem

Discussion of Common Lisp
Post Reply
Harnon
Posts: 78
Joined: Wed Jul 30, 2008 9:59 am

Arg!!! - C Interfacing Problem

Post by Harnon » Thu Jun 18, 2009 6:11 pm

I haven't had much experience with c, but I've had to dwell into it in order to figure out what i am doing wrong with my c binding.
I finally distilled it to this code -
Test C code (test.c)

typedef float testing[2];
void tester (testing* in, float a1, float a2, float a3, float a4)
{
in[0][0] = a1;
in[0][1] = a2;
in[1][0] = a3;
in[1][1] = a4;
}

What i want is to create a testing* in lisp, fill it using the function tester, and print the results back in lisp by accessing the testing* pointer. The code!:

Code: Select all

(defcfun "tester" :void (pt :pointer)
  (a1 :float) (a2 :float) (a3 :float) (a4 :float))
(cffi:with-foreign-object (a :pointer 2)
  (tester a 1.0 2.0 44.0 2.00)
  (print  (mem-aref (mem-aref a :pointer) :float))
)
I also tried this:

Code: Select all

(with-foreign-object (a :pointer 2)
  (setf (mem-aref a :pointer) (cffi:foreign-alloc :float :initial-contents '(0.0 0.0)))
  (setf (mem-aref a :pointer) (cffi:foreign-alloc :float :initial-contents '(0.0 1.0)))
  (tester a 1.0 2.0 44.0 2.00)
  (print  (mem-aref (mem-aref a :pointer) :float))
)
Each time, allegro throws an error, saying something like

Error: Attempt to take the car of #<Function MEMREF-INT> which is not listp.
[condition type: TYPE-ERROR]

I have NO clue whats wrong :oops:

Please Help!!!! :o

ramarren
Posts: 613
Joined: Sun Jun 29, 2008 4:02 am
Location: Warsaw, Poland
Contact:

Re: Arg!!! - C Interfacing Problem

Post by ramarren » Fri Jun 19, 2009 12:39 am

Some Googling shows that typedef'ing arrays is not always a good idea, since it makes C treat it strangely. As far as I can tell it makes in=(*in). Changing the C file to:

Code: Select all

void tester2 (float** in, float a1, float a2, float a3, float a4)
{
  in[0][0] = a1;
  in[0][1] = a2;
  in[1][0] = a3;
  in[1][1] = a4;
}
and Lisp code to:

Code: Select all

(cffi:defcfun "tester2" :void (pt :pointer)
              (a1 :float) (a2 :float) (a3 :float) (a4 :float))
(defun test ()
  (cffi:with-foreign-objects ((a :pointer 2)
                              (a1 :float 2)
                              (a2 :float 2))
    (setf (cffi:mem-aref a :pointer 0) a1
          (cffi:mem-aref a :pointer 1) a2)
    (tester2 a 1.0 2.0 44.0 2.00)
    (print (vector (cffi:mem-aref (cffi:mem-aref a :pointer 0) :float 0)
                   (cffi:mem-aref (cffi:mem-aref a :pointer 0) :float 1)
                   (cffi:mem-aref (cffi:mem-aref a :pointer 1) :float 0)
                   (cffi:mem-aref (cffi:mem-aref a :pointer 1) :float 1)))))
works.

With original C version the two float arrays seems to be flattened into a single vector, and just:

Code: Select all

(defun test ()
  (cffi:with-foreign-object (a :float 4)
    (tester a 1.0 2.0 44.0 2.00)
    (print (vector (cffi:mem-aref a :float 0)
                   (cffi:mem-aref a :float 1)
                   (cffi:mem-aref a :float 2)
                   (cffi:mem-aref a :float 3)))))
works. I suppose this is somewhat logical, as when you substitute typedef in C you get:

Code: Select all

testing* => (float[2])(*) => float[2][]
which is a two-dimensional array, which is a vector in a way.

Harnon
Posts: 78
Joined: Wed Jul 30, 2008 9:59 am

Re: Arg!!! - C Interfacing Problem

Post by Harnon » Fri Jun 19, 2009 7:41 pm

Thx! That worked perfectly. :mrgreen:

Post Reply