diff options
author | Ludovic Courtès <ludo@gnu.org> | 2010-03-20 16:45:14 +0100 |
---|---|---|
committer | Ludovic Courtès <ludo@gnu.org> | 2010-03-20 16:45:14 +0100 |
commit | a2c6904911577b51c2486ad7115a4311524d4a96 (patch) | |
tree | 819331df8ad9f6ff6c04d914889a8eaf3e790514 | |
parent | 7f10a113c5f370071647c23b21b912ecceef3a50 (diff) | |
download | guile-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.c | 22 |
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++) |