[cffi-devel] Re: Cannot call function with char** arg

Luís Oliveira luismbo at gmail.com
Thu Apr 20 22:08:29 UTC 2006


Nikolai Nespor <nikolai.nespor at utanet.at> writes:
> (defvar *cmd* (list "test.rrd" "--step=300" "DS:a:GAUGE:600:U:U" "DS:b:GAUGE:600:U:U" "RRA:AVERAGE:0.5:1:300"))
>
> (cffi:defcfun "rrd_create" :int (argcount :int) (args :pointer))
>
> (cffi:with-foreign-pointer (ptr (+ (reduce #'+ (map 'vector #'length
> *cmd*))(length *cmd*) 6))
>   (cffi:lisp-string-to-foreign "dummy" ptr 6) ; librrd needs a dummy fst arg
>   (let ((curptr (cffi:inc-pointer ptr 6)))
>     (dolist (param *cmd*)
>       (let ((size (1+ (length param))))
>         (cffi:lisp-string-to-foreign param curptr size)
>         (setf curptr (cffi:inc-pointer curptr size)))))
>   (rrd-create 6 ptr))

IIUC, you're allocating a bunch of memory of stuffing the 6 strings
sequentially. This is not equivalent to what your C test code is
doing. Translated to C, the above Lisp code would look something like
this:

  char *ptr = malloc(<length of *cmd* strings + 6>);
  char *p = ptr;

  strncpy(p, "dummy", 6);
  p += 6;
  
  for (<each string>) {
    strncpy(p, <nth string>, <size of nth string>);
    p += <size of nth string>;
  }

  rrd_create(6, ptr);

Which is not what rdd_create is expecting. Your C code should look
something like this translating to CFFI:

  (with-foreign-pointer (ptr (1+ (reduce #'+ *cmd* :key #'length)))
    (setf (mem-ref ptr :pointer) (foreign-string-alloc "dummy"))
    (loop for i from 1 and param in *cmd* do
          (setf (mem-aref ptr :pointer i) (foreign-string-alloc (nth i *cmd*))))
    (rdd-create 6 ptr)
    ;; free the strings here
    )

Hmm, we really need an array type in CFFI.

-- 
Luís Oliveira
luismbo (@) gmail (.) com
Equipa Portuguesa do Translation Project
http://www.iro.umontreal.ca/translation/registry.cgi?team=pt




More information about the cffi-devel mailing list