[gambit-list] gambit-c pcre loadable library crashes at

Christian christian at pflanze.mine.nu
Sun Oct 22 06:50:04 EDT 2006


At 21:32 Uhr -0500 19.10.2006, Ben Weaver wrote:
>Any help is appreciated.

I don't know the problem of your ___make_vector invocation. But:

>On a related note, is there a benefit to
>constructing a vector like this in C-space versus making a c-lambda to
>grab an entry from the int[] and constructing the vector in
>scheme-space instead?  I considered both options, but my rational for
>constructing the vector in C-space is to minimize the number of FFI
>calls needed to process a match.

There is the ##c-code special form with which you can embedd C code 
directly into scheme, and which has no overhead at all. But note that 
I've grabbed this from reading the Gambit sources, I don't know 
whether Marc thinks it's a good idea if users are making use of this.

You can represent C pointers as scheme fixnums if they are aligned to 
word boundaries (the fixnum is then representing the *word* index, 
not byte index), so there's no conversion overhead (but you loose 
type checking by the C compiler, of course). For example:

(define (mem-addressword obj) ;; returns a fixnum, which may be negative.
   (##c-code
    "___RESULT= ___MEM_ALLOCATED(___ARG1)
              ? (___ARG1 &~ ___CAST(___WORD,3)) /* creates a fixnum */
              : ___FAL;"
    obj))

So something like this may be better to work with (untested!):

(c-define "#define WORDADDRESS_AS(x,cast) ((cast)(___INT(x)*___WS))")

(define (match:rc match-addressword)
   (##c-code "___RESULT= ___FIX(WORDADDRESS_AS(___ARG1, 
c_wrap_pcre_match *)->rc);"  ;; assumes that rc is in fixnum range!
             match-addressword))

(define (match:ovecsize match-addressword)
   (##c-code "___RESULT= ___FIX(WORDADDRESS_AS(___ARG1, 
c_wrap_pcre_match *)->ovecsize);" ;; dito
             match-addressword))

;;( one could generate the above (and more) accessors through a macro )

(define (wrap-pcre-match-ovector match) ;; match is an adressword fixnum
   (and (= match-addressword 0) ;; could also use ##fixnum.=
        (let ((limit (match:rc match)))
          (and (>= limit 0)
               (let* ((limit (* 2
                               (if (= limit 0)
                                   (/ (match:ovecsize match) 3)
                                   limit)))
                      (vec (##make-vector limit)))
                  (let lp ((i 0))
                     (if (< i limit)
                         (begin
                           (vector-set! vec i
                              (##c-code "___RESULT= 
___FIX(WORDADDRESS_AS(___ARG1, c_wrap_pcre_match 
*)->ovector[___INT(___ARG2)];"
                               match i))
                           (lp (+ i 1)))))
                  vec)))))


If the integer values are not guaranteed to be within fixnum range, 
either use a c-lambda for the conversion (maybe Marc could look into 
making c-lambda faster in such cases?), or use your code (maybe the 
whole C for loop) inside ##c-code. Or use u32- or s32vectors (or the 
64bit counterparts if necessary, choosing the right ones (at 
compilation (difficult?)) or init time by checking the size of the 
integer type).

It may be easier to work this way since you can play interactively 
with the C parts from the repl. And Gambit will allocate small 
vectors as movable objects this way, which can be up to about 3 times 
faster than using still objects. OTOH, by using the fixnum pointer 
representation you're playing unsafe (you could instead use foreign 
pointer objects (during development and switch to fixnums at the 
end)).

Christian.



More information about the Gambit-list mailing list