On Fri, Dec 26, 2008 at 9:54 AM, Ben Simon <span dir="ltr"><<a href="mailto:benjisimon@gmail.com">benjisimon@gmail.com</a>></span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div class="Ih2E3d">On Fri, Dec 26, 2008 at 7:16 AM, troels knak-nielsen <span dir="ltr"><<a href="mailto:troelskn@gmail.com" target="_blank">troelskn@gmail.com</a>></span> wrote:<br></div><div class="gmail_quote"><div class="Ih2E3d">
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
I had a similar problem a few months back. Have a look over here:<br>
<a href="http://stackoverflow.com/questions/105816/how-do-i-access-a-char-through-ffi-in-plt-scheme" target="_blank">http://stackoverflow.com/questions/105816/how-do-i-access-a-char-through-ffi-in-plt-scheme</a></blockquote>
</div><div><br>Figures, the exact question I was asking was already asked - typical.<br><br>The answer doesn't really make sense to me. But, it gives me a place to start, and I'll mull it over from there.</div></div>
</blockquote><div><br>I've mulled it over, and gotten closer, but am not quite there yet.<br><br>The return type of mysql-fetch-row is described as:<br><br><div style="margin-left: 40px;">This is a type-safe representation of one row of data. It is currently
implemented as an array of counted byte strings. <br><br></div>If I ignore for a second that they are byte counted strings, and not strings represented by a final null, I can write:<br><br><div style="margin-left: 40px;">
(defmysql mysql-fetch-row : _result -> (_vector o _string (mysql-field-count)))<br></div><br>(see below for all the source code. Though, everything after the : above is re-written into a (_fun ...))<br><br>This works remarkably well, but mysql-fetch-row returns NULL to signify the end of result set has been reached.<br>
<br>With the above, I get the following error message when the end of a result set is hit:<br><br> ptr-ref: expects type <non-null-cpointer> as 1st argument, given: #f; other arguments were: #<ctype> 1<br><br>
Any suggestions for how to handle this?<br><br>I feel like I want to somehow use _cpointer/null - but just wrapping the above in a _cpointer/null doesn't appear to help.<br><br>Also, to make this really robust, I'm going to need to think of this as a vector of _pointer's and then make byte strings out of them using the lenghts mysql tells me about. Part of this solution seems straightforward:<br>
<br> ;; careful, psudo code below<br> (define _row (make-ctype (_vector o _pointer (mysql-field-count)) #f<br> (lambda (row)<br> ;; row is a vector of _pointer's into strings<br>
(for/list ([ptr row]<br> [length (mysql-fetch-lengths RESULT)])<br> (<span class="schemeparen"></span><a name="(dep._((lib._scribblings/foreign/unsafe-foreign..ss)._make-sized-byte-string))"></a><a name="(def._((lib._scribblings/foreign/unsafe-foreign..ss)._make-sized-byte-string))"></a><span title="Provided from: scribblings/foreign/unsafe-foreign"><span class="schemesymbol"><a href="file:///C:/Program%20Files/PLT/doc/foreign/foreign_pointer-funcs.html#%28def._%28%28lib._scribblings/foreign/unsafe-foreign..ss%29._make-sized-byte-string%29%29" class="schemevaluelink">make-sized-byte-string</a></span></span><span class="hspace"> </span><span class="schemevariable">ptr </span><span class="hspace"></span><span class="schemevariable">length</span><span class="schemeparen">)</span><span class="hspace">))))<br>
<br><br>The tricky part here is that I need access to RESULT - which is the value passed into mysql-fetch-row. Any suggestions for how I can arrange for this argument to be available for the ctype of resulting row?<br><br>
Thanks again for all help. Hopefully, this knowledge will be useful to others who come along and want to develop their own FFIs.<br><br>-Ben<br><br>(require scheme/foreign)<br>(unsafe!)<br><br>(define current-mysql-handle (make-parameter #f))<br>
<br>(define libmysql (ffi-lib "libmysql"))<br><br>(define _handle (make-ctype _pointer #f <br> (lambda (handle) <br> (when handle (register-finalizer handle mysql-close))<br>
handle)))<br><br>(define _result (make-ctype _pointer #f<br> (lambda (results)<br> (when results (register-finalizer results mysql-free-result))<br>
results)))<br><br>(define _data (make-ctype _pointer #f<br> (lambda (data)<br> (if data<br> data<br> (error 'mysql (mysql-error))))))<br>
<br>(define _ok? (make-ctype _int #f<br> (lambda (val)<br> (if (= val 0) #t<br> (error 'mysql (mysql-error))))))<br><br>(define-fun-syntax _handle*<br>
(syntax-id-rules ()<br> [_ (type: _handle expr: (current-mysql-handle))]))<br><br>(define-fun-syntax _null_ptr*<br> (syntax-id-rules ()<br> [_ (type: _pointer expr: #f)]))<br><br>(define-syntax defmysql <br> (syntax-rules (:)<br>
[(_ name : type ...)<br> (define name (get-ffi-obj (regexp-replaces 'name '((#rx"-" "_") (#rx"[*?]$" "")))<br> libmysql (_fun type ...)))]))<br>
<br>(defmysql mysql-init : _null_ptr* -> _handle)<br>(defmysql mysql-close : _handle -> _void)<br>(defmysql mysql-error : _handle* -> _string)<br><br>(current-mysql-handle (mysql-init))<br><br>(defmysql mysql-real-connect :<br>
_handle* _string _string _string _string _int _string _long -> _data)<br><br>(defmysql mysql-ping : _handle* -> _ok?)<br><br>(defmysql mysql-query : _handle* _string -> _ok?)<br>(defmysql mysql-free-result : _handle* _result -> _void)<br>
(defmysql mysql-store-result : _handle* -> _result)<br>(defmysql mysql-num-fields : _result -> _int)<br>(defmysql mysql-num-rows : _result -> _int)<br>(defmysql mysql-field-count : _handle* -> _int)<br>(defmysql mysql-fetch-row : _result -> (_vector o _string (mysql-field-count)))<br>
(defmysql mysql-fetch-lengths : _result -> (_vector o _long (mysql-field-count)))<br><br><br>;; TEST CODE<br>(define (do-test)<br> (mysql-real-connect "localhost" "root" "PASSWORD" "DATABASE" 0 "" 0)<br>
(mysql-query "select ID, user_login from wp_users")<br> (printf "You've got: ~a columns.\n" (mysql-field-count))<br> (let ([r (mysql-store-result)])<br> (let loop ([i 0] [row (mysql-fetch-row r)])<br>
(cond (row <br> (printf "Row: ~a\n" i)<br> (printf " ~a\n" row)<br> (printf "\n")<br> (loop (add1 i) (mysql-fetch-row r)))<br>
(else 'done)))))<br> <br> <br><br><br><br><br><br></span></div></div><br>-- <br>Have an idea for software? I can make it happen - <a href="http://www.ideas2executables.com">http://www.ideas2executables.com</a><br>
My Blog: <a href="http://benjisimon.blogspot.com">http://benjisimon.blogspot.com</a><br>