Subject: [clisp-list] FFI: variable size values

From: Sam Steingold <[email-masked]>
Date: Mon Aug 4 12:39:03 2003

Consider the following workaround:

void* null_terminate (void *garbage, void *data, int size, int num_el) {
  static char buf[BUFSIZ];
  if (size*num_el>BUFSIZ) abort();
  memset(buf,0,BUFSIZ*sizeof(char));
  memcpy(buf,data,size*num_el);
  return buf;
}

(def-call-out null_terminate_float
  (:arguments (prob-vec c-pointer) (size int) (num int))
  (:return-type (c-array-max float #.MAX_STATE))
  (:name "null_terminate"))

prob-vec comes from a function returning an array of floats.
(GetNodeBeliefs_bn).
call it like this:

(setq b (netica::GetNodeBeliefs_bn *tuberculosis*))
(setq n (netica::GetNodeNumberStates_bn *tuberculosis*))
(setq s (ffi:sizeof 'float))
(setq r (netica::null_terminate_float b s n))

b=#<FOREIGN-ADDRESS #x011AA458>
n=2
s=4

in null_terminate:
(garbage=0x22b19c, data=0x11aa458, size=4, num_el=2)

 *** where does garbage=0x22b19c come from ???!!!

the return vector buf happens to be 0-filled.
on converting the first return vector element to a single-float, I get

*** - floating point underflow

something is terribly wrong...
  
-- 
Sam Steingold (http://www.podval.org/~sds) running w2k
<http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/>
<http://www.mideasttruth.com/> <http://www.palestine-central.com/links.html>
((lambda (x) `(,x ',x)) '(lambda (x) `(,x ',x)))

---

From: "Hoehle, Joerg-Cyril" <[email-masked]>
Date: Wed Aug 6 08:09:12 2003

Sam wrote:

>Jorg, __PLEASE__ do explain to me why I have to use the "garbage"
>variable!!!
Oops, I didn't realize that this was a "is this something for a bug report" sort of query and not a "how do I FFI"?

>why do I see "prob-vec" in "data" not in "garbage"??!!

The C-ARRAY-MAX return-type (not a pointer to such an array) may be the cause. For some compilers or rather calling conventions, when passing structs or for some return types, the caller must supply an extra pointer which will be used to fill the results.

That could well explain what you observe.

You should either use (c-ptr (c-array[-max])), c-array-ptr or c-pointer (and with-c-var etc. for dynamic arrays) for :return-type.

Passing structs or arrays without an intervening pointer is never a good idea in C.

Regards,
	Jorg Hohle.