From: Robin
Subject: FFI woes ("bogus stack frame")
Date: 
Message-ID: <b87cc3ff-e642-4953-9125-6d62f87d597c@e23g2000prf.googlegroups.com>
I've downloaded a set of CFFI bindings for OpenGL and they work well
on SBCL Win32.
Now I've made some attempts to make bindings for a library called
Simple OpenGL Image Library(SOIL),
but success eludes me, and sice OpenGL worked I'm thinking it's my
fault.

The library only came with a .lib for static linking, so I've made
some attempts to make a .dll file.
The problem is that I get an access violation error when I try to use
it from lisp ("bogus stack frame").
My theory is that it has something to do with calling convention or
some such thing, and I've tried to
explicitly use the stdcall convention, but with no luck.

Here's a summary of my efforts:


.h file:
    ...
    #define SOIL_CC __stdcall
    #define SOIL_API(ret) __declspec(dllexport) ret SOIL_CC
    ...
    SOIL_API(unsigned int) SOIL_load_OGL_texture(
        const char *filename,
        int force_channels,
        unsigned int reuse_texture_ID,
        unsigned int flags
    );
    ...



.c file:
    ...
    unsigned int SOIL_CC SOIL_load_OGL_texture (
        const char *filename,
        int force_channels,
        unsigned int reuse_texture_ID,
        unsigned int flags
    ) ...



Compilation(using MinGW):
    gcc -O2 -Wall -shared <source files> -lopengl32 -o SOIL.dll -Wl,--
output-def=SOIL.def,--add-stdcall-alias



Resulting .def file:
    EXPORTS
        ...
        SOIL_load_OGL_texture = ·····················@16 @17
        ·····················@16 @18
        ...



.lisp file:
    (cffi:define-foreign-library soil
      (:windows "SOIL.dll" :calling-convention :stdcall))

    (cffi:use-foreign-library soil)

    (cffi:with-foreign-string (filename "c:/rock.jpg")
      (print (cffi:foreign-funcall "SOIL_load_OGL_texture" :pointer
filename :int 0 :unsigned-int 0 :unsigned-int 2 :unsigned-int)))

The first two statements run just fine.

What SLIME tells me upon running the third:
    EXCEPTION_ACCESS_VIOLATION
       [Condition of type SIMPLE-ERROR]

    Restarts:
     0: [ABORT] Abort SLIME compilation.
     1: [ABORT] Return to SLIME's top level.
     2: [CLOSE-CONNECTION] Close SLIME connection
     3: [ABORT] Exit debugger, returning to top level.

    Backtrace:
      0: ("bogus stack frame")
      1: ("foreign function: #x65AC3AE7")
      2: ("foreign function: #x65AC53A7")
      3: ((SB-C::TOP-LEVEL-FORM
           (LET ((PTR #1="#<...>" . #1#))
             (UNWIND-PROTECT #1# . #1#))))
      4: (SB-FASL::LOAD-FASL-GROUP
          #<SB-SYS:FD-STREAM for "file c:\\s6qg.8.fasl" {AF2F7E1}>)
      5: ((FLET SB-THREAD::WITH-RECURSIVE-LOCK-THUNK))
      6: (SB-FASL::LOAD-AS-FASL
          #<SB-SYS:FD-STREAM for "file c:\\s6qg.8.fasl" {AF2F7E1}>
          NIL
          #<unavailable argument>)


Can anybody give me a helping hand?
From: Dimiter "malkia" Stanev
Subject: Re: FFI woes ("bogus stack frame")
Date: 
Message-ID: <5rpqojF16a74kU1@mid.individual.net>
I've looked into the SBCL source code (1.0.12) and there notes that on 
SBCL it does not matter what the convention is (__stdcall, or cdecl) as 
they always preserve ESP, and restore it after the call.

I would guess that CFFI goes through that code.

But still it might not work correctly, if less arguments were provided 
to the function, because with __stdcall the caller pops the arguments 
from the stack, and it might pop more than needed, and trash the saved 
ESP (not sure here).

But in your case you are providing the correct number of arguments.

Did it work with just the _cdecl convention? Or compiling it with MSVC?

Robin wrote:
> I've downloaded a set of CFFI bindings for OpenGL and they work well
> on SBCL Win32.
> Now I've made some attempts to make bindings for a library called
> Simple OpenGL Image Library(SOIL),
> but success eludes me, and sice OpenGL worked I'm thinking it's my
> fault.
> 
> The library only came with a .lib for static linking, so I've made
> some attempts to make a .dll file.
> The problem is that I get an access violation error when I try to use
> it from lisp ("bogus stack frame").
> My theory is that it has something to do with calling convention or
> some such thing, and I've tried to
> explicitly use the stdcall convention, but with no luck.
> 
> Here's a summary of my efforts:
> 
> 
> ..h file:
>     ...
>     #define SOIL_CC __stdcall
>     #define SOIL_API(ret) __declspec(dllexport) ret SOIL_CC
>     ...
>     SOIL_API(unsigned int) SOIL_load_OGL_texture(
>         const char *filename,
>         int force_channels,
>         unsigned int reuse_texture_ID,
>         unsigned int flags
>     );
>     ...
> 
> 
> 
> ..c file:
>     ...
>     unsigned int SOIL_CC SOIL_load_OGL_texture (
>         const char *filename,
>         int force_channels,
>         unsigned int reuse_texture_ID,
>         unsigned int flags
>     ) ...
> 
> 
> 
> Compilation(using MinGW):
>     gcc -O2 -Wall -shared <source files> -lopengl32 -o SOIL.dll -Wl,--
> output-def=SOIL.def,--add-stdcall-alias
> 
> 
> 
> Resulting .def file:
>     EXPORTS
>         ...
>         SOIL_load_OGL_texture = ·····················@16 @17
>         ·····················@16 @18
>         ...
> 
> 
> 
> ..lisp file:
>     (cffi:define-foreign-library soil
>       (:windows "SOIL.dll" :calling-convention :stdcall))
> 
>     (cffi:use-foreign-library soil)
> 
>     (cffi:with-foreign-string (filename "c:/rock.jpg")
>       (print (cffi:foreign-funcall "SOIL_load_OGL_texture" :pointer
> filename :int 0 :unsigned-int 0 :unsigned-int 2 :unsigned-int)))
> 
> The first two statements run just fine.
> 
> What SLIME tells me upon running the third:
>     EXCEPTION_ACCESS_VIOLATION
>        [Condition of type SIMPLE-ERROR]
> 
>     Restarts:
>      0: [ABORT] Abort SLIME compilation.
>      1: [ABORT] Return to SLIME's top level.
>      2: [CLOSE-CONNECTION] Close SLIME connection
>      3: [ABORT] Exit debugger, returning to top level.
> 
>     Backtrace:
>       0: ("bogus stack frame")
>       1: ("foreign function: #x65AC3AE7")
>       2: ("foreign function: #x65AC53A7")
>       3: ((SB-C::TOP-LEVEL-FORM
>            (LET ((PTR #1="#<...>" . #1#))
>              (UNWIND-PROTECT #1# . #1#))))
>       4: (SB-FASL::LOAD-FASL-GROUP
>           #<SB-SYS:FD-STREAM for "file c:\\s6qg.8.fasl" {AF2F7E1}>)
>       5: ((FLET SB-THREAD::WITH-RECURSIVE-LOCK-THUNK))
>       6: (SB-FASL::LOAD-AS-FASL
>           #<SB-SYS:FD-STREAM for "file c:\\s6qg.8.fasl" {AF2F7E1}>
>           NIL
>           #<unavailable argument>)
> 
> 
> Can anybody give me a helping hand?