chickadee » foreign » access

Accessing externally defined data

For a list of the special forms that allow definition of Scheme procedures that access native C/C++ code, consult the documentation on the (chicken foreign) module. The remainder of this chapter merely explains a few special cases.

Returning large objects or chunks of memory to Scheme

When you call a C function which needs to return quantities of data, several issues arise:

So some would advise you to just return a pointer to Scheme, use memcpy or any other function(s) which you need to get the data into CHICKEN-managed memory and into the desired kind of data structure, then free the C data. For this example, we are trying to return an array of doubles into an f64vector; we can accomplish that by adding a specialized copy function to the C library being integrated:

void CopyResults(double* vector) {
    memcpy(vector, bezierBuffer, totalOutputPoints * sizeof(double));
}

// The original C function which takes an array of doubles, 
// does some sort of transmogrification,
// retains a new malloc'd array of the results
// and returns the count
int GenerateResults(double* vector, int count) {
    ... 
}

and the "egg" which calls the C functions can be implemented like this:

(module memcpy-demo (input->output)
    (import (chicken base) scheme (chicken foreign) srfi-4)

    (define CopyResults (foreign-lambda void "CopyResults" f64vector))

    (define GenerateResults (foreign-lambda integer "GenerateResults" f64vector integer))

    (define (input->output input)
        (let* ([size (GenerateResults input (f64vector-length input))] 
               [vect (make-f64vector size)])
            (printf "returned size ~a~%" size)
            (CopyResults vect)
            vect)))

The foreign-lambda takes care of the details in this case so that an f64vector allocated in the nursery can be treated as a plain old array of doubles in C (assuming your C compiler uses 64-bit values for double).

Various eggs provide other examples, and some of them do it more efficiently too, but this method is relatively clean and compact.


Previous: Interface to external functions and variables

Next: Foreign type specifiers