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.