[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