summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWayne Meissner <wmeissner@gmail.com>2009-09-20 08:06:13 +1000
committerWayne Meissner <wmeissner@gmail.com>2009-09-20 08:06:13 +1000
commit805ae16a952ccdcdafaccf98ce7dabd4d49db96c (patch)
tree4d66d65c8c25d59974283b7b6645b00cdf4d75b8
parent04765a959094f42be66209813ad903fc661bc62f (diff)
downloadffi-805ae16a952ccdcdafaccf98ce7dabd4d49db96c.tar.gz
Allow callback params through long-arg invokers
-rw-r--r--ext/ffi_c/Call.c68
1 files changed, 67 insertions, 1 deletions
diff --git a/ext/ffi_c/Call.c b/ext/ffi_c/Call.c
index bed1983..d213de4 100644
--- a/ext/ffi_c/Call.c
+++ b/ext/ffi_c/Call.c
@@ -89,6 +89,7 @@ static VALUE rbffi_InvokeLLLrL(int argc, VALUE* argv, void* function, FunctionTy
static VALUE rbffi_InvokeLLLLrL(int argc, VALUE* argv, void* function, FunctionType* fnInfo);
static VALUE rbffi_InvokeLLLLLrL(int argc, VALUE* argv, void* function, FunctionType* fnInfo);
static VALUE rbffi_InvokeLLLLLLrL(int argc, VALUE* argv, void* function, FunctionType* fnInfo);
+static VALUE rbffi_InvokeLongParams(int argc, VALUE* argv, void* function, FunctionType* fnInfo);
#endif
@@ -460,6 +461,8 @@ rbffi_GetInvoker(FunctionType *fnInfo)
case NATIVE_BUFFER_IN:
case NATIVE_BUFFER_OUT:
case NATIVE_BUFFER_INOUT:
+ case NATIVE_FUNCTION:
+ case NATIVE_CALLBACK:
break;
default:
fastLong = false;
@@ -467,7 +470,7 @@ rbffi_GetInvoker(FunctionType *fnInfo)
}
}
- if (fastLong) {
+ if (fastLong && fnInfo->callbackCount < 1) {
switch (fnInfo->parameterCount) {
case 0:
return rbffi_InvokeVrL;
@@ -487,6 +490,9 @@ rbffi_GetInvoker(FunctionType *fnInfo)
default:
break;
}
+
+ } else if (fastLong && fnInfo->parameterCount <= 6) {
+ return rbffi_InvokeLongParams;
}
#endif
@@ -754,6 +760,66 @@ rbffi_InvokeLLLLLLrL(int argc, VALUE* argv, void* function, FunctionType* fnInfo
LARG(fnInfo, argv, 3), LARG(fnInfo, argv, 4), LARG(fnInfo, argv, 5));
}
+static VALUE
+rbffi_InvokeLongParams(int argc, VALUE* argv, void* function, FunctionType* fnInfo)
+{
+ void **ffiValues = NULL;
+ FFIStorage* params = NULL;
+ L result;
+
+ if (fnInfo->parameterCount > 0) {
+ ffiValues = ALLOCA_N(void *, fnInfo->parameterCount);
+ params = ALLOCA_N(FFIStorage, fnInfo->parameterCount);
+
+ rbffi_SetupCallParams(argc, argv,
+ fnInfo->parameterCount, fnInfo->nativeParameterTypes, params, ffiValues,
+ fnInfo->callbackParameters, fnInfo->callbackCount, fnInfo->rbEnums);
+
+ switch (fnInfo->parameterCount) {
+ case 0:
+ result = ((L(*)(void)) function)();
+ break;
+
+ case 1:
+ result = ((L(*)(L)) function)(*(L *) ffiValues[0]);
+ break;
+
+ case 2:
+ result = ((L(*)(L, L)) function)(*(L *) ffiValues[0],
+ *(L *) ffiValues[1]);
+ break;
+
+ case 3:
+ result = ((L(*)(L, L, L)) function)(*(L *) ffiValues[0],
+ *(L *) ffiValues[1], *(L *) ffiValues[2]);
+ break;
+
+ case 4:
+ result = ((L(*)(L, L, L, L)) function)(*(L *) ffiValues[0],
+ *(L *) ffiValues[1], *(L *) ffiValues[2], *(L *) ffiValues[3]);
+ break;
+
+ case 5:
+ result = ((L(*)(L, L, L, L, L)) function)(*(L *) ffiValues[0],
+ *(L *) ffiValues[1], *(L *) ffiValues[2], *(L *) ffiValues[3],
+ *(L *) ffiValues[4]);
+ break;
+
+ case 6:
+ result = ((L(*)(L, L, L, L, L, L)) function)(*(L *) ffiValues[0],
+ *(L *) ffiValues[1], *(L *) ffiValues[2], *(L *) ffiValues[3],
+ *(L *) ffiValues[4], *(L *) ffiValues[5]);
+ break;
+
+ default:
+ rb_raise(rb_eRuntimeError, "BUG: should not reach this point");
+ return Qnil;
+ }
+ }
+
+ return returnL(fnInfo, &result);
+}
+
#endif /* BYPASS_FFI */
static void*