[gambit-list] How to get the correct Tag for a call to POINTER_to_SCMOBJ (FFI)

Till tritill at gmail.com
Fri Jul 15 11:24:59 EDT 2011


Im creating a scheme list of pointers to c-structs in a c-function similar to the STRINGS_to_SCMOBJ example in section 19.6 of the gambit manual. The only difference being that i put pointers into the list via POINTER_to_SCMOBJ. This works fine as long as i pass ___FAL as the second parameter and gambit treats the pointer as foreign.

Now i have a c-define-type e.g.:

(c-define-type Node* (pointer "Node"))

And some c-lambdas, e.g.:

(define rotate-node 
    (c-lambda (Node* float) void "___arg1->rotate(___arg2)))

(define get-childnodes
    (c-lambda (Node*) scheme-object "LIST_to_SCMOBJ<Node*>(___arg1->childs(), &___result);")))

By calling (get-childnodes foonode), i get a list of pointers to the childs. If i now pass one of the pointers in the list to (rotate-node childnode) it segfaults, because - im just guessing - the types foreign and Node* are not compatible. If i define Node* with #f in the tag field to omit typechecks:

(c-define-type Node* (pointer "Node" #f))

It works. But i would like to preserve the typecheck by passing the right tag to POINTER_to_SCMOBJ and getting pointers with the exact type information. While digging around the generated c files i found some places where i could get it from, e.g. the ___C_OBJ_(N) defines, but it does not seem like i could rely on those, because the order can always change and i would have to look them up after compiling...

Is it possible to get the right type-tag or does it even make sense to do so? This is my first attemp at the FFI and im probably messing stuff up, because some things are unclear to me. E.g. what is the purpose of the arg_num parameter which is passed to all the *_to_SCMOBJ functions?

Im also not defining the ___BEGIN_CFUN, ___END_CFUN and SFUN macros and do not create an extra c-define-type for the list of nodes. In the STRINGS_to_SCMOBJ example a comment says:

/*
   * Note that result is either the empty list or a ___STILL pair
   * with a reference count equal to 1.  There will be a call to
   * ___release_scmobj later on (in ___END_CFUN_STRINGS_to_SCMOBJ
   * or ___END_SFUN_STRINGS_to_SCMOBJ) that will allow the garbage
   * collector to reclaim the whole list of strings when the Scheme
   * world no longer references it.
   */

Does that mean, that in my case the returned scheme-object from get-childnodes would never be collected? Here is the LIST_to_SCMOBJ function:

template<typename T>
___SCMOBJ LIST_to_SCMOBJ(const List<T> *src, ___SCMOBJ *dst) {
  ___SCMOBJ ___err = ___FIX(___NO_ERR);
  ___SCMOBJ result = ___NUL;

  const ListIter<T> iter = src->iter();
  while(iter.moveNext()) {
    ___SCMOBJ item = ___NUL;
    ___err = ___POINTER_to_SCMOBJ(iter.current(), ___FAL, NULL, &item, 0);
    
     ___SCMOBJ newresult = ___EXT(___make_pair)(item, newresult, ___STILL);

    ___EXT(___release_scmobj)(item);
    ___EXT(___release_scmobj)(result);

    result = newresult;
    
    if (___FIXNUMP(result)) {
      return result;
    }
  }

 *dst = result;
  
  return ___FIX(___NO_ERR);
}


And Hello everyone who read this far ;) this is my first post here.
Cheers, Till


More information about the Gambit-list mailing list