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)