Permalink
View
@@ -50,6 +50,7 @@
#include "Type.h"
#include "LastError.h"
#include "Call.h"
+#include "MappedType.h"
#ifdef USE_RAW
# ifndef __i386__
@@ -94,10 +95,10 @@ static VALUE rbffi_InvokeLongParams(int argc, VALUE* argv, void* function, Funct
#endif
-static ID id_to_ptr, id_map_symbol;
+static ID id_to_ptr, id_map_symbol, id_to_native;
void
-rbffi_SetupCallParams(int argc, VALUE* argv, int paramCount, NativeType* paramTypes,
+rbffi_SetupCallParams(int argc, VALUE* argv, int paramCount, Type** paramTypes,
FFIStorage* paramStorage, void** ffiValues,
VALUE* callbackParameters, int callbackCount, VALUE enums)
{
@@ -116,10 +117,20 @@ rbffi_SetupCallParams(int argc, VALUE* argv, int paramCount, NativeType* paramTy
argCount = paramCount != -1 ? paramCount : argc;
for (i = 0, argidx = 0, cbidx = 0; i < argCount; ++i) {
- int type = argidx < argc ? TYPE(argv[argidx]) : T_NONE;
+ Type* paramType = paramTypes[i];
+ int type;
+
+
+ if (unlikely(paramType->nativeType == NATIVE_MAPPED)) {
+ VALUE values[] = { argv[argidx], Qnil };
+ argv[argidx] = rb_funcall2(((MappedType *) paramType)->rbConverter, id_to_native, 2, values);
+ paramType = ((MappedType *) paramType)->type;
+ }
+
+ type = argidx < argc ? TYPE(argv[argidx]) : T_NONE;
ffiValues[i] = param;
- switch (paramTypes[i]) {
+ switch (paramType->nativeType) {
case NATIVE_INT8:
param->s8 = getSignedInt(argv[argidx++], type, -128, 127, "char", Qnil);
@@ -248,7 +259,7 @@ rbffi_SetupCallParams(int argc, VALUE* argv, int paramCount, NativeType* paramTy
break;
default:
- rb_raise(rb_eArgError, "Invalid parameter type: %d", paramTypes[i]);
+ rb_raise(rb_eArgError, "Invalid parameter type: %d", paramType->nativeType);
}
}
}
@@ -286,7 +297,7 @@ rbffi_CallFunction(int argc, VALUE* argv, void* function, FunctionType* fnInfo)
retval = alloca(MAX(fnInfo->ffi_cif.rtype->size, FFI_SIZEOF_ARG));
rbffi_SetupCallParams(argc, argv,
- fnInfo->parameterCount, fnInfo->nativeParameterTypes, params, ffiValues,
+ fnInfo->parameterCount, fnInfo->parameterTypes, params, ffiValues,
fnInfo->callbackParameters, fnInfo->callbackCount, fnInfo->rbEnums);
#if defined(HAVE_NATIVETHREAD) && defined(HAVE_RB_THREAD_BLOCKING_REGION)
@@ -800,7 +811,7 @@ rbffi_InvokeLongParams(int argc, VALUE* argv, void* function, FunctionType* fnIn
params = ALLOCA_N(FFIStorage, fnInfo->parameterCount);
rbffi_SetupCallParams(argc, argv,
- fnInfo->parameterCount, fnInfo->nativeParameterTypes, params, ffiValues,
+ fnInfo->parameterCount, fnInfo->parameterTypes, params, ffiValues,
fnInfo->callbackParameters, fnInfo->callbackCount, fnInfo->rbEnums);
switch (fnInfo->parameterCount) {
@@ -876,6 +887,7 @@ void
rbffi_Call_Init(VALUE moduleFFI)
{
id_to_ptr = rb_intern("to_ptr");
+ id_to_native = rb_intern("to_native");
id_map_symbol = rb_intern("__map_symbol");
}
View
@@ -69,7 +69,7 @@ typedef union {
extern void rbffi_Call_Init(VALUE moduleFFI);
-extern void rbffi_SetupCallParams(int argc, VALUE* argv, int paramCount, NativeType* paramTypes,
+extern void rbffi_SetupCallParams(int argc, VALUE* argv, int paramCount, Type** paramTypes,
FFIStorage* paramStorage, void** ffiValues,
VALUE* callbackParameters, int callbackCount, VALUE enums);
@@ -0,0 +1,62 @@
+
+#include <ruby.h>
+
+#include <ffi.h>
+#include "rbffi.h"
+
+#include "Type.h"
+#include "MappedType.h"
+
+
+VALUE rbffi_DataConverterClass = Qnil;
+static ID id_native_type_ivar;
+
+static VALUE
+conv_native_type(int argc, VALUE* argv, VALUE self)
+{
+ if (argc == 0) {
+ if (!rb_ivar_defined(self, id_native_type_ivar)) {
+ rb_raise(rb_eNotImpError, "native_type method not overridden and no native_type set");
+ }
+
+ return rb_ivar_get(self, id_native_type_ivar);
+
+ } else if (argc == 1) {
+ VALUE type = rbffi_Type_Find(argv[0]);
+
+ rb_ivar_set(self, id_native_type_ivar, type);
+
+ return type;
+
+ } else {
+ rb_raise(rb_eArgError, "incorrect arguments");
+ }
+}
+
+static VALUE
+conv_to_native(VALUE self, VALUE value, VALUE ctx)
+{
+ return value;
+}
+
+static VALUE
+conv_from_native(VALUE self, VALUE value, VALUE ctx)
+{
+ return value;
+}
+
+
+
+void
+rbffi_DataConverter_Init(VALUE moduleFFI)
+{
+ rbffi_DataConverterClass = rb_define_module_under(moduleFFI, "DataConverter");
+
+ rb_define_method(rbffi_DataConverterClass, "native_type", conv_native_type, -1);
+ rb_define_method(rbffi_DataConverterClass, "to_native", conv_to_native, 2);
+ rb_define_method(rbffi_DataConverterClass, "from_native", conv_from_native, 2);
+
+ id_native_type_ivar = rb_intern("@native_type");
+}
+
+
View
@@ -55,6 +55,7 @@
#include "Call.h"
#include "ClosurePool.h"
#include "Function.h"
+#include "MappedType.h"
typedef struct Function_ {
AbstractMemory memory;
@@ -100,7 +101,7 @@ VALUE rbffi_FunctionClass = Qnil;
static VALUE async_cb_thread = Qnil;
#endif
-static ID id_call = 0, id_cbtable = 0, id_cb_ref = 0;
+static ID id_call = 0, id_to_native = 0, id_from_native = 0, id_cbtable = 0, id_cb_ref = 0;
struct gvl_callback {
Closure* closure;
@@ -501,16 +502,26 @@ callback_with_gvl(void* data)
Function* fn = (Function *) cb->closure->info;
FunctionType *cbInfo = fn->info;
+ Type* returnType = cbInfo->returnType;
void* retval = cb->retval;
void** parameters = cb->parameters;
VALUE* rbParams;
+ VALUE rbReturnType = cbInfo->rbReturnType;
VALUE rbReturnValue;
int i;
rbParams = ALLOCA_N(VALUE, cbInfo->parameterCount);
for (i = 0; i < cbInfo->parameterCount; ++i) {
VALUE param;
- switch (cbInfo->parameterTypes[i]->nativeType) {
+ Type* paramType = cbInfo->parameterTypes[i];
+ VALUE rbParamType = rb_ary_entry(cbInfo->rbParameterTypes, i);
+
+ if (unlikely(paramType->nativeType == NATIVE_MAPPED)) {
+ paramType = ((MappedType *) paramType)->type;
+ rbParamType = ((MappedType *) paramType)->rbType;
+ }
+
+ switch (paramType->nativeType) {
case NATIVE_INT8:
param = INT2NUM(*(int8_t *) parameters[i]);
break;
@@ -560,22 +571,35 @@ callback_with_gvl(void* data)
case NATIVE_FUNCTION:
case NATIVE_CALLBACK:
case NATIVE_STRUCT:
- param = rbffi_NativeValue_ToRuby(cbInfo->parameterTypes[i],
- rb_ary_entry(cbInfo->rbParameterTypes, i), parameters[i], Qnil);
+ param = rbffi_NativeValue_ToRuby(paramType, rbParamType, parameters[i], Qnil);
break;
default:
param = Qnil;
break;
}
+
+ // Convert the native value into a custom ruby value
+ if (unlikely(cbInfo->parameterTypes[i]->nativeType == NATIVE_MAPPED)) {
+ VALUE values = { param, Qnil };
+ param = rb_funcall2(((MappedType *) cbInfo->parameterTypes[i])->rbConverter, id_from_native, 2, values);
+ }
+
rbParams[i] = param;
}
rbReturnValue = rb_funcall2(fn->rbProc, id_call, cbInfo->parameterCount, rbParams);
+
+ if (unlikely(returnType->nativeType == NATIVE_MAPPED)) {
+ VALUE values = { rbReturnValue, Qnil };
+ rbReturnValue = rb_funcall2(((MappedType *) returnType)->rbConverter, id_to_native, 2, values);
+ rbReturnType = ((MappedType *) returnType)->rbType;
+ returnType = ((MappedType* ) returnType)->type;
+ }
if (rbReturnValue == Qnil || TYPE(rbReturnValue) == T_NIL) {
- memset(retval, 0, cbInfo->ffiReturnType->size);
- } else switch (cbInfo->returnType->nativeType) {
+ memset(retval, 0, returnType->ffiType->size);
+ } else switch (returnType->nativeType) {
case NATIVE_INT8:
case NATIVE_INT16:
case NATIVE_INT32:
@@ -626,7 +650,7 @@ callback_with_gvl(void* data)
} else if (rb_obj_is_kind_of(rbReturnValue, rb_cProc) || rb_respond_to(rbReturnValue, id_call)) {
VALUE function;
- function = rbffi_Function_ForProc(cbInfo->rbReturnType, rbReturnValue);
+ function = rbffi_Function_ForProc(rbReturnType, rbReturnValue);
*((void **) retval) = ((AbstractMemory *) DATA_PTR(function))->address;
} else {
@@ -639,14 +663,14 @@ callback_with_gvl(void* data)
AbstractMemory* memory = ((Struct *) DATA_PTR(rbReturnValue))->pointer;
if (memory->address != NULL) {
- memcpy(retval, memory->address, cbInfo->ffiReturnType->size);
+ memcpy(retval, memory->address, returnType->ffiType->size);
} else {
- memset(retval, 0, cbInfo->ffiReturnType->size);
+ memset(retval, 0, returnType->ffiType->size);
}
} else {
- memset(retval, 0, cbInfo->ffiReturnType->size);
+ memset(retval, 0, returnType->ffiType->size);
}
break;
@@ -694,5 +718,7 @@ rbffi_Function_Init(VALUE moduleFFI)
id_call = rb_intern("call");
id_cbtable = rb_intern("@__ffi_callback_table__");
id_cb_ref = rb_intern("@__ffi_callback__");
+ id_to_native = rb_intern("to_native");
+ id_from_native = rb_intern("from_native");
}
Oops, something went wrong.

0 comments on commit daa6030

Please sign in to comment.