Hello, I'm using SBCL version 1.2.4, CFFI version 0.14.0, and libffi version 3.1. I've been trying to pass a struct by value using CFFI and libffi. I'm a newbie to both CFFI and Lisp so I had to piece this together from the manual as well as some of the unit tests that come with CFFI. I'm getting an error that I just can't get past:
The value READ-FUNC is not of type SB-SYS:SYSTEM-AREA-POINTER
The library I'm trying to wrap is libvorbisfile, which decodes Ogg Vorbis files. It has an init function called ov_open_callbacks:
int ov_open_callbacks(void *datasource, OggVorbis_File *vf, const char *initial, long ibytes, ov_callbacks callbacks);
The part it's choking on is the last argument, a struct, passed by value, of callback functions:
typedef struct { size_t (*read_func) (void *ptr, size_t size, size_t nmemb, void *datasource); int (*seek_func) (void *datasource, ogg_int64_t offset, int whence); int (*close_func) (void *datasource); long (*tell_func) (void *datasource); } ov_callbacks;
The library is designed to use one of a few static structs defined in a header file. Since it's defined in the header file and not in libvorbisfile.so, I must create CFFI translation code. There were a lot of other structs I had to wrap with CFFI as well. Here is my code:
Does anyone have any clues about what I'm doing wrong here?
(Regarding my previous email about getting CFFI working on Debian jessie, it turns out the Debian version of cl-alexandria is missing a file and cl-cffi is buggy, so I just added the missing file and installed the CFFI source by hand. Thanks for the response, Fau.)
Marshall
Looks like you're sending it a list of symbols 'read-func etc. '(read-func seek-func (null-pointer) tell-func) is a list of two symbols, a list, then another symbol. It needs to be a plist (property list) with alternating slot names and values (list 'read-func read-func 'seek-func seek-func...) (At the moment I can't remember if the slot names are in the keyword package or not, so you might need :read-func instead of 'read-func etc.)
Liam
On Thu, Apr 30, 2015 at 7:28 PM, Marshall Mason marshallmason2@gmail.com wrote:
Hello, I'm using SBCL version 1.2.4, CFFI version 0.14.0, and libffi version 3.1. I've been trying to pass a struct by value using CFFI and libffi. I'm a newbie to both CFFI and Lisp so I had to piece this together from the manual as well as some of the unit tests that come with CFFI. I'm getting an error that I just can't get past:
The value READ-FUNC is not of type SB-SYS:SYSTEM-AREA-POINTER
The library I'm trying to wrap is libvorbisfile, which decodes Ogg Vorbis files. It has an init function called ov_open_callbacks:
int ov_open_callbacks(void *datasource, OggVorbis_File *vf, const char *initial, long ibytes, ov_callbacks callbacks);
The part it's choking on is the last argument, a struct, passed by value, of callback functions:
typedef struct { size_t (*read_func) (void *ptr, size_t size, size_t nmemb, void *datasource); int (*seek_func) (void *datasource, ogg_int64_t offset, int whence); int (*close_func) (void *datasource); long (*tell_func) (void *datasource); } ov_callbacks;
The library is designed to use one of a few static structs defined in a header file. Since it's defined in the header file and not in libvorbisfile.so, I must create CFFI translation code. There were a lot of other structs I had to wrap with CFFI as well. Here is my code:
Does anyone have any clues about what I'm doing wrong here?
(Regarding my previous email about getting CFFI working on Debian jessie, it turns out the Debian version of cl-alexandria is missing a file and cl-cffi is buggy, so I just added the missing file and installed the CFFI source by hand. Thanks for the response, Fau.)
Marshall
Hi Liam, Thanks for the response. It works! Actually, there was one hitch, which I'd like to explain, if for no other reason than posterity.
I had translate-into-foreign-memory, translate-to-foreign, and free-translated object defined, which were supposed to unpack a list (using first, second, third, and fourth), not a plist. The list I sent had two symbols, a list, and a symbol, as you said. Perhaps I didn't understand the ' quote function, but I thought it was supposed to interpret stuff inside the list. That's my Lisp ignorance showing.
Because I had those three methods defined, changing to a plist as you suggested didn't work. I tried just removing the methods entirely, assuming perhaps what you were getting at here is that CFFI can accept plists by default, so that the methods only need to be defined if you want to use a custom mechanism for passing the structs. This worked! I didn't know about this important feature. I didn't see it in the manual, or any of my Google searches.
Thanks so much for your help!
Marshall
On Thu, Apr 30, 2015 at 6:27 PM, Liam Healy lnp@healy.washington.dc.us wrote:
Looks like you're sending it a list of symbols 'read-func etc. '(read-func seek-func (null-pointer) tell-func) is a list of two symbols, a list, then another symbol. It needs to be a plist (property list) with alternating slot names and values (list 'read-func read-func 'seek-func seek-func...) (At the moment I can't remember if the slot names are in the keyword package or not, so you might need :read-func instead of 'read-func etc.)
Liam
On Thu, Apr 30, 2015 at 7:28 PM, Marshall Mason marshallmason2@gmail.com wrote:
Hello, I'm using SBCL version 1.2.4, CFFI version 0.14.0, and libffi version
3.1.
I've been trying to pass a struct by value using CFFI and libffi. I'm a newbie to both CFFI and Lisp so I had to piece this together from the
manual
as well as some of the unit tests that come with CFFI. I'm getting an
error
that I just can't get past:
The value READ-FUNC is not of type SB-SYS:SYSTEM-AREA-POINTER
The library I'm trying to wrap is libvorbisfile, which decodes Ogg Vorbis files. It has an init function called ov_open_callbacks:
int ov_open_callbacks(void *datasource, OggVorbis_File *vf, const char *initial, long ibytes, ov_callbacks callbacks);
The part it's choking on is the last argument, a struct, passed by
value, of
callback functions:
typedef struct { size_t (*read_func) (void *ptr, size_t size, size_t nmemb, void *datasource); int (*seek_func) (void *datasource, ogg_int64_t offset, int
whence);
int (*close_func) (void *datasource); long (*tell_func) (void *datasource);
} ov_callbacks;
The library is designed to use one of a few static structs defined in a header file. Since it's defined in the header file and not in libvorbisfile.so, I must create CFFI translation code. There were a lot
of
other structs I had to wrap with CFFI as well. Here is my code:
Does anyone have any clues about what I'm doing wrong here?
(Regarding my previous email about getting CFFI working on Debian
jessie, it
turns out the Debian version of cl-alexandria is missing a file and
cl-cffi
is buggy, so I just added the missing file and installed the CFFI source
by
hand. Thanks for the response, Fau.)
Marshall