one of the cffi/TODO items has -> Handle va_list. For now it's treated as any other argument.
Maybe someone has thought deeply about how to do this? Please let me know if you have any suggestions.
[It seems borodust/claw tries to handle this by converting va_list args to variadic lisp arguments - but it still seems to blow up at a cffi:parse-type. Or maybe it is a defect with my Clang-7.0 stdarg vs. what is included with gcc]
On Wed, 15 Jul 2020 at 06:16, Madhu enometh@meer.net wrote:
one of the cffi/TODO items has -> Handle va_list. For now it's treated as any other argument.
Maybe someone has thought deeply about how to do this? Please let me know if you have any suggestions.
[It seems borodust/claw tries to handle this by converting va_list args to variadic lisp arguments - but it still seems to blow up at a cffi:parse-type. Or maybe it is a defect with my Clang-7.0 stdarg vs. what is included with gcc]
The TODO item should probably be removed. DEFCFUN has syntax for varargs and that's implemented on top of FOREIGN-FUNCALL-VARARGS and FOREIGN-FUNCALL-VARARGS-POINTER. The implementation so far is simple, it only takes care of promoting floats to doubles, and chars/short to ints. The test suite tracks whether this works and it seems to work so far.
Not sure about what c2ffi needs to do, though.
* Luís Oliveira luismbo@gmail.com CAB-HnLQJE9Y0+kyq3-COjCk-GD3mzOOE+h2f+7upkdkCGu9+Ww@mail.gmail.com Wrote on Wed, 15 Jul 2020 14:50:27 +0100
On Wed, 15 Jul 2020 at 06:16, Madhu enometh@meer.net wrote:
one of the cffi/TODO items has -> Handle va_list. For now it's treated as any other argument.
Maybe someone has thought deeply about how to do this? Please let me know if you have any suggestions.
[It seems borodust/claw tries to handle this by converting va_list args to variadic lisp arguments - but it still seems to blow up at a cffi:parse-type. Or maybe it is a defect with my Clang-7.0 stdarg vs. what is included with gcc]
The TODO item should probably be removed. DEFCFUN has syntax for varargs and that's implemented on top of FOREIGN-FUNCALL-VARARGS and FOREIGN-FUNCALL-VARARGS-POINTER. The implementation so far is simple, it only takes care of promoting floats to doubles, and chars/short to ints. The test suite tracks whether this works and it seems to work so far.
The TODO entry was about specifically va_list. Now I'm not sure how the "new" stdargs API can be manipulated through CFFI - AFAIK it is purely a C compiler thing - you cannot foreign funcall to va_start and va_copy. The only way I could use it is through lisp implementations that support a form of c-inline, or through "grovelled" code which would be loaded through a shared library.
Not sure about what c2ffi needs to do, though.
In order to "treat va_list as any other argument" I tried adding an opaque (cffi:defcstruct (:builtin-va-list :size 192)) -- 192 being sizeof(va_list) with x86_64-pc-linux-gnu-gcc -- having %json-type-to-cffi-type return that when it comes across a cffi tag "__builtin_va_list". cffi/c2ffi can generate defcfns for functions which use va_list in the signature. I think the user would still be hardpressed to find a way to use them.
Unless I'm missing something... ??
The TODO entry was about specifically va_list. Now I'm not sure how the "new" stdargs API can be manipulated through CFFI - AFAIK it is purely a C compiler thing - you cannot foreign funcall to va_start and va_copy. The only way I could use it is through lisp implementations that support a form of c-inline, or through "grovelled" code which would be loaded through a shared library.
IIRC libffi has support for dealing with varargs.
there could be a new system called cffi/c2ffi+libffi, or somesuch, that expands to cffi+libffi definitions? or is the cffi + libffi integration transparent and loaded on-demand? looks like that.
or straight out depend on libffi by cffi/c2ffi? i don't think that's a good idea, though, without some hard-pressing reasons.
i don't feel the urge to get into actually hacking on this, but i'll be happy to answer questions about the cffi/c2ffi code.
* Attila Lendvai attila@lendvai.name CAE4vfcKMTRrYu37wy-WCRgTDrZjdB_h6nD6tRtq26civ6CibtQ@mail.gmail.com Wrote on Thu, 16 Jul 2020 10:06:46 +0200
The TODO entry was about specifically va_list. Now I'm not sure how the "new" stdargs API can be manipulated through CFFI - AFAIK it is purely a C compiler thing - you cannot foreign funcall to va_start and va_copy. The only way I could use it is through lisp implementations that support a form of c-inline, or through "grovelled" code which would be loaded through a shared library.
IIRC libffi has support for dealing with varargs.
there could be a new system called cffi/c2ffi+libffi, or somesuch, that expands to cffi+libffi definitions? or is the cffi + libffi integration transparent and loaded on-demand? looks like that.
yes when you call something that passes structures by value libffi will translate structures by value if libffi is loaded or it'll show you an error indicating you should load the cffi-libffi system.
[BTW *foreign-structures-by-value* is intially set to a lambda function which throws a restartable error. It offers a restart - to load the cffi-libffi system. when that system is loaded value of the variable will be overwritten.
But there is a bug: the restart won't proceed with the foreign funcall The last line withing that lambda form should be
(funcall *foreign-structures-by-value* args)
so that instead of returning to the caller it will proceed with the intended funcall ]
or straight out depend on libffi by cffi/c2ffi? i don't think that's a good idea, though, without some hard-pressing reasons.
i don't feel the urge to get into actually hacking on this, but i'll be happy to answer questions about the cffi/c2ffi code.
[I do have some other questions] But as luis noted varargs already works- eg. cffi/c2ffi translates functions of the form int foo(int a, ...) to a (defcfun foo :int ((a :int) &rest)) - which you can call as (foo 42 :char #\c)
However the varargs machinery seems to be old - it predates the fsbv machinery and so it doesn't work when the defcfun form has struct arguments. I expect to hit this corner case soon and I hope I'll be the fix will be trivial - since foreign-funcall already works.
I'd think that will be sufficient without having to introduce libffi machinery for varargs. Right?
[I vaguely remember seeing a comment by the author about some part of libffi which was not yet implemented - probably on the mailing list - or a comment or document in the code code was reorganized and removed. was it perhaps about varargs? ]
My initial post on this thread only dealt with functions of the form
int foo(int a, va_list arg)
which cffi/c2ffi was skipping without generating a defcfun because it didn't have a type for va_list. As I noted elsewhere these would be hard to use anyway,
On Thu, 16 Jul 2020 11:42:17 +0530 (IST), Madhu said:
Wrote on Wed, 15 Jul 2020 14:50:27 +0100
On Wed, 15 Jul 2020 at 06:16, Madhu enometh@meer.net wrote:
one of the cffi/TODO items has -> Handle va_list. For now it's treated as any other argument.
Maybe someone has thought deeply about how to do this? Please let me know if you have any suggestions.
[It seems borodust/claw tries to handle this by converting va_list args to variadic lisp arguments - but it still seems to blow up at a cffi:parse-type. Or maybe it is a defect with my Clang-7.0 stdarg vs. what is included with gcc]
The TODO item should probably be removed. DEFCFUN has syntax for varargs and that's implemented on top of FOREIGN-FUNCALL-VARARGS and FOREIGN-FUNCALL-VARARGS-POINTER. The implementation so far is simple, it only takes care of promoting floats to doubles, and chars/short to ints. The test suite tracks whether this works and it seems to work so far.
The TODO entry was about specifically va_list. Now I'm not sure how the "new" stdargs API can be manipulated through CFFI - AFAIK it is purely a C compiler thing - you cannot foreign funcall to va_start and va_copy. The only way I could use it is through lisp implementations that support a form of c-inline, or through "grovelled" code which would be loaded through a shared library.
Not sure about what c2ffi needs to do, though.
In order to "treat va_list as any other argument" I tried adding an opaque (cffi:defcstruct (:builtin-va-list :size 192)) -- 192 being sizeof(va_list) with x86_64-pc-linux-gnu-gcc -- having %json-type-to-cffi-type return that when it comes across a cffi tag "__builtin_va_list". cffi/c2ffi can generate defcfns for functions which use va_list in the signature. I think the user would still be hardpressed to find a way to use them.
Unless I'm missing something... ??
I think this defcstruct is wrong on x86_64-pc-linux-gnu-gcc for two reasons:
1. sizeof(va_list) is 24 bytes for me.
2. It is an array, not a struct, so it is passed as a pointer.
I.e.
int bar(va_list z) { return sizeof(z); }
will return the same as sizeof(void *).
__Martin
* Martin Simmons martin@lispworks.com 202007161039.06GAdKKb016862@higson.cam.lispworks.com Wrote on Thu, 16 Jul 2020 11:39:20 +0100
On Thu, 16 Jul 2020 11:42:17 +0530 (IST), Madhu said:
In order to "treat va_list as any other argument" I tried adding an opaque (cffi:defcstruct (:builtin-va-list :size 192)) -- 192 being sizeof(va_list) with x86_64-pc-linux-gnu-gcc -- having %json-type-to-cffi-type return that when it comes across a cffi tag "__builtin_va_list". cffi/c2ffi can generate defcfns for functions which use va_list in the signature. I think the user would still be hardpressed to find a way to use them.
I think this defcstruct is wrong on x86_64-pc-linux-gnu-gcc for two reasons:
sizeof(va_list) is 24 bytes for me.
It is an array, not a struct, so it is passed as a pointer.
I.e.
int bar(va_list z) { return sizeof(z); }
will return the same as sizeof(void *).
mea culpa on both counts. i see it is defined be an array type so it is always handled as a pointer.