summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2010-03-20 16:45:14 +0100
committerLudovic Courtès <ludo@gnu.org>2010-03-20 16:45:14 +0100
commita2c6904911577b51c2486ad7115a4311524d4a96 (patch)
tree819331df8ad9f6ff6c04d914889a8eaf3e790514
parent7f10a113c5f370071647c23b21b912ecceef3a50 (diff)
downloadguile-a2c6904911577b51c2486ad7115a4311524d4a96.tar.gz
Fix argument passing to foreign functions.
* libguile/foreign.c (scm_i_foreign_call): When allocating room for DATA, use the sum of all the argument sizes, not `cif->bytes'.
-rw-r--r--libguile/foreign.c22
1 files changed, 17 insertions, 5 deletions
diff --git a/libguile/foreign.c b/libguile/foreign.c
index 52ed10c57..1488b5848 100644
--- a/libguile/foreign.c
+++ b/libguile/foreign.c
@@ -952,16 +952,28 @@ scm_i_foreign_call (SCM foreign, SCM *argv)
void *rvalue;
void **args;
unsigned i;
+ size_t arg_size;
scm_t_ptrdiff off;
cif = SCM_FOREIGN_POINTER (scm_car (foreign), ffi_cif);
func = SCM_FOREIGN_POINTER (scm_cdr (foreign), void);
-
- /* arg pointers */
+
+ /* Argument pointers. */
args = alloca (sizeof(void*) * cif->nargs);
- /* arg values, then return type value */
- data = alloca (ROUND_UP (cif->bytes, cif->rtype->alignment)
- + cif->rtype->size);
+
+ /* Compute the amount of memory needed to store all the argument values.
+ Note: as of libffi 3.0.9 `cif->bytes' is undocumented and is zero, so it
+ can't be used for that purpose. */
+ for (i = 0, arg_size = 0;
+ i < cif->nargs;
+ i++, arg_size)
+ arg_size += ROUND_UP (cif->arg_types[i]->size,
+ cif->arg_types[i]->alignment);
+
+ /* Space for argument values, followed by return value. */
+ data = alloca (arg_size
+ + ROUND_UP (cif->rtype->size, cif->rtype->alignment));
+
/* unpack argv to native values, setting argv pointers */
off = 0;
for (i = 0; i < cif->nargs; i++)