Using CFFI: dealing with a writeback buffer

Orivej Desh c at orivej.org
Wed Jul 15 01:26:39 UTC 2015


> I don't know if it is the best place to ask this question, but I'll try it. I am trying to wrap around a following function:
> 
> OGRErr OSRExportToProj4(OGRSpatialReferenceH r, char **buff);
> 
> This function allocates the string and assigns it to the (char*) pointer passed as buff and then its contents should be copied into a C string and the obtained pointer released via CPLFree();

For the sake of example, I assume the pointer size is 8 bytes.

First you learn elsewhere that OGRSpatialReferenceH is a pointer and OGRErr is an int. [1]

Then you know that OSRExportToProj4 takes two pointers and writes to the memory addressed by the second argument a pointer (char*),
so the second argument must point to an allocated memory region 8 bytes in size; in CFFI, you usually allocate memory using WITH-FOREIGN-OBJECT.

After OSRExportToProj4 wrote a pointer to a C-string into that region of memory, you can read it back in CFFI as a pointer using (MEM-REF ... :POINTER).

When you hold a pointer to a C-string, you can convert it into a Lisp string with FOREIGN-STRING-TO-LISP.

Overall, you need something like

     (cffi:defcfun (%osr-export-to-proj-4 "OSRExportToProj4") :int
       (handle :pointer)
       (*str :pointer))

     (defun osr-export-to-proj-4 (handle)
       (cffi:with-foreign-object (*str :pointer)
         (%osr-export-to-proj-4 handle *str)
         (let ((str (cffi:mem-ref *str :pointer)))
           (unwind-protect (cffi:foreign-string-to-lisp str)
             (cpl-free str)))))


[1] One way to learn it is with c2ffi (https://github.com/rpav/c2ffi):

     $ c2ffi -D sexp /usr/include/gdal/ogr_geometry.h 2>/dev/null | awk '$2 ~ "OGRErr|OGRSpatialReferenceH|OSRExportToProj4" {print}'
     (typedef OGRErr :int)
     (typedef OGRSpatialReferenceH (:pointer :void))
     (function "OSRExportToProj4" ((OGRSpatialReferenceH) ((:pointer (:pointer :char)))) OGRErr)



More information about the cffi-devel mailing list