Nikolai Nespor nikolai.nespor@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.