Hello,
I'm working to write CFFI binding for libclang [1], I've used swig to generate CFFI declarations of all libclang bindings, and I'm hoping to wrap those in a nice CLOS-based interface (my code is up here [2]).
However I've run into an error which I'm having trouble getting past. Although the following simple C code [3] compiles and runs w/o problem. A direct translation into lisp [4] using the swig-generated cffi bindings throws this error [5]. For some reason the `clang_getTranslationUnitCursor' function always throws an error. FWIW I'll include the original C function headers [6] and the swig-generate CFFI declarations [7] below.
I'm using SBCL version 1.0.57 and CFFI version 0.10.6 installed with quicklisp.
Any idea what could be causing this error? Could the problem lie in SBCL, in CFFI, or possibly in some difference in state between the C world and the lisp world?
Thanks,
Footnotes: [1] http://clang.llvm.org/doxygen/group__CINDEX.html
[2] https://github.com/eschulte/cl-libclang
[3] hello-cursor.c // -*- C -*- #include "clang-c/Index.h" #include <stdio.h>
int main(int argc, char *argv[]) { // declare CXIndex Idx; CXTranslationUnit TU; CXCursor CU; enum CXCursorKind Kind;
// initialize Idx = clang_createIndex(0, 0); TU = clang_createTranslationUnit(Idx, "hello.ast"); CU = clang_getTranslationUnitCursor(TU); Kind = clang_getCursorKind(CU);
// is the cursor null if(clang_Cursor_isNull(CU)) return 1; else printf("cursor is not null\n");
// cursor Kind (should be 300 for 'root') if(Kind != 300) return 1; else printf("kind of cursor is %d\n", Kind);
// cleanup clang_disposeTranslationUnit(TU); clang_disposeIndex(Idx); return 0; }
[4] hello-cursor.lisp ;; -*- lisp -*- (require :libclang) (in-package :libclang)
(defvar idx nil "CXIndex") (defvar tu nil "CXTranslationUnit") (defvar cu nil "CXCursor") (defvar kind nil "CXCursorKind")
(setf idx (clang_createIndex 0 0)) (setf tu (clang_createTranslationUnit idx "etc/hello.ast")) (setf cu (clang_getTranslationUnitCursor tu)) ;; we never get this far (setf kind (clang_getCursorKind cu))
[5] error running with SBCL 1.0.57
CORRUPTION WARNING in SBCL pid 30785(tid 140737353975552): Memory fault at 7841 (pc=0x7ffff57edb4a, sp=0x7ffff6e37508) The integrity of this image is possibly compromised. Continuing with fingers crossed.
debugger invoked on a SB-SYS:MEMORY-FAULT-ERROR in thread #<THREAD "main thread" RUNNING {1002998D93}>: Unhandled memory fault at #x3E800007841.
Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name): 0: [ABORT] Exit debugger, returning to top level.
[6] from Index.h // -*- C -*- CINDEX_LINKAGE CXIndex clang_createIndex(int excludeDeclarationsFromPCH, int displayDiagnostics); // ... CINDEX_LINKAGE CXTranslationUnit clang_createTranslationUnit(CXIndex, const char *ast_filename); // ... CINDEX_LINKAGE CXCursor clang_getTranslationUnitCursor(CXTranslationUnit);
[7] from libclang-swig.lisp ;; -*- lisp -*- (cffi:defcfun ("clang_createIndex" clang_createIndex) :pointer (excludeDeclarationsFromPCH :int) (displayDiagnostics :int)) ;; ... (cffi:defcfun ("clang_createTranslationUnit" clang_createTranslationUnit) :pointer (arg0 :pointer) (ast_filename :string)) ;; ... (cffi:defcstruct CXCursor (kind CXCursorKind) (xdata :int) (data :pointer)) ;; ... (cffi:defcfun ("clang_getTranslationUnitCursor" clang_getTranslationUnitCursor) CXCursor (arg0 :pointer))
On Sat, Jun 30, 2012 at 6:15 PM, Eric Schulte eric.schulte@gmx.com wrote:
(cffi:defcstruct CXCursor (kind CXCursorKind) (xdata :int) (data :pointer)) ;; ... (cffi:defcfun ("clang_getTranslationUnitCursor" clang_getTranslationUnitCursor) CXCursor (arg0 :pointer))
IIUC, this is the problem: clang_getTranslationUnitCursor() returns a structure by value, but SWIG has erroneously declared it to return a structure by reference. (If you have the chance, please report this bug to the SWIG maintainers, or if there's no one maintaining SWIG's CFFI backend, you can report it at CFFI's bugtracker.)
If you grab CFFI from its git repository, you'll find a new system called "cffi-libffii" which implements the passing of structures by value. (The syntax in this case would be (defcfun ... (:struct CXCursor) ...).) Let us know if you have trouble using it.
HTH,