Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

CFFI tinkering

6 views
Skip to first unread message

Francogrex

unread,
Jan 5, 2010, 5:27:56 AM1/5/10
to
I'm tinkering with cffi to have an output from an array of pointers
without sucess maybe someone can help.

In C
#include <stdio.h>
#ifdef BUILD_DLL
#define EXPORT __declspec(dllexport)
#else
#define EXPORT __declspec(dllimport)
#endif
EXPORT char *ret (void)
{
char *end[2]={"this is string-1", "I am testing this array of
pointers"};
return *end;
}

And then this in compiled into a lib and exported to CL:

(cffi:defcfun ("ret" ret) :pointer)
(defparameter returned (ret))
(loop for i from 0 below 55 collect
(code-char (cffi:mem-aref returned :char i)))
;;ok this works giving a list of chars but that's not what I want
;;I would like yo have an output of a list of two string like '("this
is string-1", "I am testing this array of pointers").
;;but this below is wrong:
;(cffi:defcfun ("ret" ret) :string)
;(defparameter returned (ret))
;; returned is just the first string: "this is string-1".
;(loop for i from 0 below 55 collect
(cffi:mem-aref returned :string i))

What is the good way to have that? (note that I am not even sure my C
code is correct as well).

Tamas K Papp

unread,
Jan 5, 2010, 5:45:12 AM1/5/10
to
On Tue, 05 Jan 2010 02:27:56 -0800, Francogrex wrote:

> I'm tinkering with cffi to have an output from an array of pointers
> without sucess maybe someone can help.
>
> In C
> #include <stdio.h>
> #ifdef BUILD_DLL
> #define EXPORT __declspec(dllexport)
> #else
> #define EXPORT __declspec(dllimport)
> #endif
> EXPORT char *ret (void)
> {
> char *end[2]={"this is string-1", "I am testing this array of
> pointers"};
> return *end;
> }

You may want to return end, not *end (which is a pointer to the first
string). Then you need to follow the pointers to _each_ string.

> And then this in compiled into a lib and exported to CL:
>
> (cffi:defcfun ("ret" ret) :pointer)
> (defparameter returned (ret))
> (loop for i from 0 below 55 collect
> (code-char (cffi:mem-aref returned :char i)))
> ;;ok this works giving a list of chars but that's not what I want ;;I
> would like yo have an output of a list of two string like '("this is

Look up STRING the the HS: "Description: A string is a specialized
vector whose elements are of type character or a subtype of type
character." So you want to convert your list (see coerce or map).
The ITERATE macro's COLLECT has a RESULT-TYPE argument which may help.

That said, CFFI's WITH-FOREIGN-POINTER-AS-STRING could be a simpler
solution.

HTH,

Tamas

Kenneth Tilton

unread,
Jan 5, 2010, 5:48:21 AM1/5/10
to

I think your C code might be the issue. It has been a while, but I would
have the monkeys try all the permutations of:

char (*end)[2];

and:

return end;

'end' in C is the name of the two element array of string pointers, ie,
the address of the two-element array of char* pointers (to your two
strings).

*end is a synonym for end[0], the first string pointer aka the address
of the first string. *(end+1) or end[1] gets you the second string pointer.

Again, it's been a while, I might be all wet.

kt

--

http://thelaughingstockatpngs.com/
http://www.facebook.com/pages/The-Laughingstock/115923141782?ref=nf

Kenneth Tilton

unread,
Jan 5, 2010, 6:26:35 AM1/5/10
to

Ah, yes, and I believe CFFI has explicit keywords (:cstring?) for
strings, at least as parameters.

kt

Francogrex

unread,
Jan 6, 2010, 10:43:20 AM1/6/10
to
On Jan 5, 11:45 am, Tamas K Papp <tkp...@gmail.com> wrote:
> You may want to return end, not *end (which is a pointer to the first
> string).  Then you need to follow the pointers to _each_ string...

Indeed and herebelow I post the solution that works for others to
learn (always good to post solutions for archiving):

#include <stdio.h>
#include <stdlib.h>
__declspec(dllexport) char ** test()
{
static char *linePtr[3]={"AEDPA", "RFE", "MAN"}; // Array of
pointers to char.
return linePtr;
}
//CFFI:
(defparameter returned (cffi:foreign-funcall "test" :pointer))
(iter (for i from 0 below 3) (collect (cffi:mem-aref returned :string
i)))

One thing to mind is that here contrary to the previous char* return,
if one goes beyond the length of the pointer of strings (3 in this
case) segmentation errors will occurr (whereas when returning char* if
one goes beyond 3, it will return garbage but will not breakdown).

0 new messages