Hi folks! Here're patches (based on stable-2.0) to fix this issue according to proposal 1.
Please review them, I'm going to write a new CFFI parser with nyacc, so these patches is important for this plan. Thanks! On Sat, 2015-01-24 at 11:33 +0100, Ludovic Courtès wrote: > Mark H Weaver <m...@netris.org> skribis: > > > l...@gnu.org (Ludovic Courtès) writes: > > > >> Chaos Eternal <chaoseter...@shlug.org> skribis: > >> > >>> Proposals to solve this bug: > >>> > >>> Proposal 1. > >>> > >>> Adding a keyword argument to pointer->procedure, if set to true, the > >>> generated wrapper will check 'errno' immediately after ffi_call and > >>> return the errno as second value. > >>> > >>> the proposed pointer->procedure maybe like this: > >>> pointer->procedure return_type func_ptr arg_types #:return-errno > I agree #1 is now the best option so far. > > Ludo’.
>From 88a99af4b5db9096c3cde51c72eb371b6be76754 Mon Sep 17 00:00:00 2001 From: Nala Ginrut <nalagin...@gmail.com> Date: Thu, 31 Dec 2015 20:27:59 +0800 Subject: [PATCH 1/2] Add option to pointer->procedure to return errno if necessary --- libguile/foreign.c | 33 ++++++++++++++++++++++++--------- libguile/foreign.h | 2 +- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/libguile/foreign.c b/libguile/foreign.c index 29cfc73..6909023 100644 --- a/libguile/foreign.c +++ b/libguile/foreign.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2010-2015 Free Software Foundation, Inc. +/* Copyright (C) 2010-2016 Free Software Foundation, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -85,7 +85,7 @@ null_pointer_error (const char *func_name) } -static SCM cif_to_procedure (SCM cif, SCM func_ptr); +static SCM cif_to_procedure (SCM cif, SCM func_ptr, SCM return_errno); static SCM pointer_weak_refs = SCM_BOOL_F; @@ -753,24 +753,29 @@ make_cif (SCM return_type, SCM arg_types, const char *caller) } #undef FUNC_NAME -SCM_DEFINE (scm_pointer_to_procedure, "pointer->procedure", 3, 0, 0, - (SCM return_type, SCM func_ptr, SCM arg_types), +SCM_DEFINE (scm_pointer_to_procedure, "pointer->procedure", 3, 1, 0, + (SCM return_type, SCM func_ptr, SCM arg_types, SCM return_errno), "Make a foreign function.\n\n" "Given the foreign void pointer @var{func_ptr}, its argument and\n" "return types @var{arg_types} and @var{return_type}, return a\n" "procedure that will pass arguments to the foreign function\n" "and return appropriate values.\n\n" "@var{arg_types} should be a list of foreign types.\n" - "@code{return_type} should be a foreign type.") + "@code{return_type} should be a foreign type.\n" + "@var{return_errno} is @code{#f} in default, if set to #t, then\n" + "the @var{errno} will be returned as the second value.") #define FUNC_NAME s_scm_pointer_to_procedure { ffi_cif *cif; SCM_VALIDATE_POINTER (2, func_ptr); + if (SCM_UNLIKELY (SCM_UNBNDP (return_errno))) + return_errno = SCM_BOOL_F; + cif = make_cif (return_type, arg_types, FUNC_NAME); - return cif_to_procedure (scm_from_pointer (cif, NULL), func_ptr); + return cif_to_procedure (scm_from_pointer (cif, NULL), func_ptr, return_errno); } #undef FUNC_NAME @@ -940,7 +945,7 @@ get_objcode_trampoline (unsigned int nargs) } static SCM -cif_to_procedure (SCM cif, SCM func_ptr) +cif_to_procedure (SCM cif, SCM func_ptr, SCM return_errno) { ffi_cif *c_cif; SCM objcode, table, ret; @@ -949,7 +954,8 @@ cif_to_procedure (SCM cif, SCM func_ptr) objcode = get_objcode_trampoline (c_cif->nargs); table = scm_c_make_vector (2, SCM_UNDEFINED); - SCM_SIMPLE_VECTOR_SET (table, 0, scm_cons (cif, func_ptr)); + SCM_SIMPLE_VECTOR_SET (table, 0, + scm_cons (cif, scm_cons (func_ptr, return_errno))); SCM_SIMPLE_VECTOR_SET (table, 1, SCM_BOOL_F); /* name */ ret = scm_make_program (objcode, table, SCM_BOOL_F); @@ -1116,9 +1122,11 @@ scm_i_foreign_call (SCM foreign, const SCM *argv) unsigned i; size_t arg_size; scm_t_ptrdiff off; + SCM return_errno; cif = SCM_POINTER_VALUE (SCM_CAR (foreign)); - func = SCM_POINTER_VALUE (SCM_CDR (foreign)); + func = SCM_POINTER_VALUE (SCM_CADR (foreign)); + return_errno = SCM_CDDR (foreign); /* Argument pointers. */ args = alloca (sizeof (void *) * cif->nargs); @@ -1153,9 +1161,16 @@ scm_i_foreign_call (SCM foreign, const SCM *argv) rvalue = (void *) ROUND_UP ((scm_t_uintptr) data + off, max (sizeof (void *), cif->rtype->alignment)); + errno = 0; /* off we go! */ ffi_call (cif, func, rvalue, args); + if (SCM_LIKELY (scm_is_true (return_errno))) + { + return scm_values (scm_list_2 (pack (cif->rtype, rvalue, 1), + scm_from_int (errno))); + } + return pack (cif->rtype, rvalue, 1); } diff --git a/libguile/foreign.h b/libguile/foreign.h index 41c0b65..8541526 100644 --- a/libguile/foreign.h +++ b/libguile/foreign.h @@ -93,7 +93,7 @@ SCM_INTERNAL SCM scm_pointer_to_string (SCM pointer, SCM length, SCM encoding); */ SCM_API SCM scm_pointer_to_procedure (SCM return_type, SCM func_ptr, - SCM arg_types); + SCM arg_types, SCM return_errno); SCM_API SCM scm_procedure_to_pointer (SCM return_type, SCM func_ptr, SCM arg_types); SCM_INTERNAL SCM scm_i_foreign_call (SCM foreign, const SCM *argv); -- 1.7.10.4
>From 71151759513f8163e45c328e5bcae8e89ebbf614 Mon Sep 17 00:00:00 2001 From: Nala Ginrut <nalagin...@gmail.com> Date: Thu, 31 Dec 2015 20:28:36 +0800 Subject: [PATCH 2/2] updated pointer->procedure in document --- doc/ref/api-foreign.texi | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/ref/api-foreign.texi b/doc/ref/api-foreign.texi index c2c49ec..9fd09f5 100644 --- a/doc/ref/api-foreign.texi +++ b/doc/ref/api-foreign.texi @@ -813,8 +813,8 @@ tightly packed structs and unions by hand. See the code for Of course, the land of C is not all nouns and no verbs: there are functions too, and Guile allows you to call them. -@deffn {Scheme Procedure} pointer->procedure return_type func_ptr arg_types -@deffnx {C Procedure} scm_pointer_to_procedure (return_type, func_ptr, arg_types) +@deffn {Scheme Procedure} pointer->procedure return_type func_ptr arg_types [return_errno=#f] +@deffnx {C Procedure} scm_pointer_to_procedure (return_type, func_ptr, arg_types, return_errno) Make a foreign function. Given the foreign void pointer @var{func_ptr}, its argument and @@ -825,6 +825,9 @@ and return appropriate values. @var{arg_types} should be a list of foreign types. @code{return_type} should be a foreign type. @xref{Foreign Types}, for more information on foreign types. +@var{return_errno} is @code{#f} in default, if set to @code{#t}, then @var{errno} +will be returned as the second value. + @end deffn Here is a better definition of @code{(math bessel)}: -- 1.7.10.4