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