[cffi-devel] usage question
Due to my pretty rusty C skills I have what I hope is a naive question. I'm writing a cffi interface to the tidy lib which among other things has the following construct: // in include file: struct _TidyBuffer; typedef struct _TidyBuffer TidyBuffer; typedef void* TidyDoc; // example caller: TidyBuffer output = {0}; TidyDoc tdoc = tidyCreate(); ... tidySaveBuffer(tdoc, &output) ... so, tidy allocates some memory from a pointer reference supplied by the client. How do I declare and pass this reference to the foreign function?
Bruce Butterfield <bruce@open-tek.com> writes:
// in include file: struct _TidyBuffer; typedef struct _TidyBuffer TidyBuffer; typedef void* TidyDoc;
// example caller: TidyBuffer output = {0}; TidyDoc tdoc = tidyCreate(); ... tidySaveBuffer(tdoc, &output) ...
This C code (you don't show the declarations for tidyCreate() and tidySaveBuffer() though) translates to something like this: (use-package :cffi) (defcstruct tidy-buffer ...) (defctype tidy-doc :pointer) ; if you prefer... (defcfun ("tidyCreate" tidy-create) :tidy-doc) (defcfun ("tidySaveBuffer" tidy-save-buffer) :void ;;? (doc tidy-doc) (out tidy-buffer)) ;; caller (with-foreign-object (output tidy-buffer) (let ((tdoc (tidy-create))) (tidy-save-buffer tdoc output))) HTH -- Luis Oliveira luismbo (@) gmail (.) com Equipa Portuguesa do Translation Project http://www.iro.umontreal.ca/translation/registry.cgi?team=pt
Luis Oliveira <luismbo@gmail.com> writes:
(defcfun ("tidyCreate" tidy-create) :tidy-doc) ^^^ Erm, that should be "tidy-doc".
-- Luis Oliveira luismbo (@) gmail (.) com Equipa Portuguesa do Translation Project http://www.iro.umontreal.ca/translation/registry.cgi?team=pt
Still having a problem and I think it's related to the allocation of the buffer. Here is C code that works fine: (BTW, I'm running SBCL 0.9.5, cffi-luis-051002-1333, on Ubuntu Hoary/x86) ================================= typedef struct { unsigned char* bp; unsigned int size; unsigned int allocated; unsigned int next; } TidyBuffer; typedef void* TidyDoc; TidyDoc tidyCreate(void); int tidyParseString(TidyDoc tdoc, const char* str); int tidySaveBuffer(TidyDoc tdoc, TidyBuffer* buf); int main(int argc, char **argv ) { const char* input = "<title>Foo</title><p>Foo!"; TidyBuffer output = {0}; TidyDoc tdoc = tidyCreate(); tidyParseString( tdoc, input ); // Parse the input tidySaveBuffer( tdoc, &output ); // Pretty Print printf( "\n%s\n", output.bp ); } =========================== and my lisp equivalent: ;;;;;;;;;;;;;;;;;;;;;;; (cffi:load-foreign-library "/usr/lib/libtidy.so") (cffi:defcstruct tidy-buffer (bp :pointer) (size :unsigned-int) (allocated :unsigned-int) (next :unsigned-int)) (cffi:defcfun ("tidyCreate" tidy-create) :pointer) (cffi:defcfun ("tidyParseString" tidy-parse-string) :int (doc :pointer) (input :pointer)) (cffi:defcfun ("tidySaveBuffer" tidy-save-buffer) :int (doc :pointer) (output tidy-buffer)) (defun tidy-string (str) (cffi:with-foreign-object (output tidy-buffer) (let ((tdoc (tidy-create))) (cffi:with-foreign-string (s str) (tidy-parse-string tdoc s) (tidy-save-buffer tdoc output))))) (tidy-string "<title>Foo</title><p>Foo!") ;;;;;;;;;;;;;;;;;;;;;;;; when it gets to the call to tidy-save-buffer I get a stack trace: memory fault [Condition of type SB-KERNEL::MEMORY-FAULT-ERROR] Restarts: 0: [ABORT] Abort SLIME compilation. 1: [ABORT-REQUEST] Abort handling SLIME request. 2: [TERMINATE-THREAD] Terminate this thread (#<THREAD "worker" {9E2F069}>) Backtrace: 0: (SB-KERNEL::MEMORY-FAULT-ERROR) 1: ("foreign function: call_into_lisp") 2: ("foreign function: post_signal_tramp") 3: ("foreign function: tidyBufPutByte") 4: ("foreign function: #xB5EF69F7") 5: ("foreign function: tidyPutByte") 6: ("foreign function: #xB5EF8359") 7: ("foreign function: WriteChar") 8: ("foreign function: PFlushLine") 9: ("foreign function: PPrintTree") 10: ("foreign function: PPrintTree") 11: ("foreign function: tidyDocSaveStream") 12: ("foreign function: tidyDocSaveBuffer") 13: ("foreign function: tidySaveBuffer") 14: (TIDY-SAVE-BUFFER #.(SB-SYS:INT-SAP #X0827B590) #.(SB-SYS:INT-SAP #XB5A3DFEC)) 15: (TIDY-STRING "<title>Foo</title><p>Foo!") 16: ((SB-PCL::FAST-METHOD SWANK-BACKEND:SWANK-COMPILE-STRING (T)) #<unused argument> #<unused argument> "(tidy-string \"<title>Foo</title><p>Foo!\") " (:BUFFER "tinytidy.lisp" :POSITION 624 :DIRECTORY "/home/bruce/src/cl/"))
Hello, Bruce Butterfield <bruce@open-tek.com> writes:
Still having a problem and I think it's related to the allocation of the buffer. Here is C code that works fine:
Yes, sort of.
(BTW, I'm running SBCL 0.9.5, cffi-luis-051002-1333, on Ubuntu Hoary/x86)
================================= typedef struct { unsigned char* bp; unsigned int size; unsigned int allocated; unsigned int next; } TidyBuffer;
typedef void* TidyDoc;
TidyDoc tidyCreate(void); int tidyParseString(TidyDoc tdoc, const char* str); int tidySaveBuffer(TidyDoc tdoc, TidyBuffer* buf);
int main(int argc, char **argv ) { const char* input = "<title>Foo</title><p>Foo!"; TidyBuffer output = {0};
The equivalent lisp code to this assignment was missing: (loop for i below (cffi:foreign-type-size 'tidy-buffer) do (setf (mem-ref output :char i) 0))
TidyDoc tdoc = tidyCreate(); tidyParseString( tdoc, input ); // Parse the input tidySaveBuffer( tdoc, &output ); // Pretty Print
printf( "\n%s\n", output.bp ); }
[snip]
when it gets to the call to tidy-save-buffer I get a stack trace:
memory fault [Condition of type SB-KERNEL::MEMORY-FAULT-ERROR]
Restarts: 0: [ABORT] Abort SLIME compilation. 1: [ABORT-REQUEST] Abort handling SLIME request. 2: [TERMINATE-THREAD] Terminate this thread (#<THREAD "worker" {9E2F069}>)
Backtrace: 0: (SB-KERNEL::MEMORY-FAULT-ERROR) 1: ("foreign function: call_into_lisp") 2: ("foreign function: post_signal_tramp") 3: ("foreign function: tidyBufPutByte") ^^^^^^^^^^^^^^ And somewhere around there a random pointer was being realloc()'ed. (or something like that)
4: ("foreign function: #xB5EF69F7") 5: ("foreign function: tidyPutByte") 6: ("foreign function: #xB5EF8359") 7: ("foreign function: WriteChar") 8: ("foreign function: PFlushLine") 9: ("foreign function: PPrintTree") 10: ("foreign function: PPrintTree") 11: ("foreign function: tidyDocSaveStream") 12: ("foreign function: tidyDocSaveBuffer") 13: ("foreign function: tidySaveBuffer") 14: (TIDY-SAVE-BUFFER #.(SB-SYS:INT-SAP #X0827B590) #.(SB-SYS:INT-SAP #XB5A3DFEC)) 15: (TIDY-STRING "<title>Foo</title><p>Foo!") 16: ((SB-PCL::FAST-METHOD SWANK-BACKEND:SWANK-COMPILE-STRING (T)) #<unused argument> #<unused argument> "(tidy-string \"<title>Foo</title><p>Foo!\") " (:BUFFER "tinytidy.lisp" :POSITION 624 :DIRECTORY "/home/bruce/src/cl/"))
HTH -- Luís Oliveira luismbo (@) gmail (.) com Equipa Portuguesa do Translation Project http://www.iro.umontreal.ca/translation/registry.cgi?team=pt
participants (2)
-
Bruce Butterfield
-
Luis Oliveira