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).
> 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
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
Ah, yes, and I believe CFFI has explicit keywords (:cstring?) for
strings, at least as parameters.
kt
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).