diff options
-rw-r--r-- | Rakefile | 3 | ||||
-rw-r--r-- | ext/ffi_c/AbstractMemory.c | 2 | ||||
-rw-r--r-- | ext/ffi_c/ArrayType.c | 12 | ||||
-rw-r--r-- | ext/ffi_c/Buffer.c | 11 | ||||
-rw-r--r-- | ext/ffi_c/DynamicLibrary.c | 29 | ||||
-rw-r--r-- | ext/ffi_c/Function.c | 17 | ||||
-rw-r--r-- | ext/ffi_c/FunctionInfo.c | 26 | ||||
-rw-r--r-- | ext/ffi_c/MappedType.c | 23 | ||||
-rw-r--r-- | ext/ffi_c/MethodHandle.c | 4 | ||||
-rw-r--r-- | ext/ffi_c/Pointer.c | 11 | ||||
-rw-r--r-- | ext/ffi_c/Struct.c | 39 | ||||
-rw-r--r-- | ext/ffi_c/StructByValue.c | 16 | ||||
-rw-r--r-- | ext/ffi_c/StructLayout.c | 39 | ||||
-rw-r--r-- | ext/ffi_c/Type.c | 29 | ||||
-rw-r--r-- | ext/ffi_c/Variadic.c | 17 | ||||
-rw-r--r-- | ext/ffi_c/compat.h | 30 | ||||
-rwxr-xr-x | ext/ffi_c/extconf.rb | 2 | ||||
m--------- | ext/ffi_c/libffi | 0 | ||||
-rw-r--r-- | lib/ffi/platform/sw_64-linux/types.conf | 141 | ||||
-rw-r--r-- | spec/ffi/function_spec.rb | 10 |
20 files changed, 379 insertions, 82 deletions
@@ -31,8 +31,7 @@ CLEAN.include 'spec/ffi/fixtures/*.o' CLEAN.include 'spec/ffi/embed-test/ext/*.{o,def}' CLEAN.include 'spec/ffi/embed-test/ext/Makefile' CLEAN.include "pkg/ffi-*-{mingw32,java}" -CLEAN.include 'lib/1.*' -CLEAN.include 'lib/2.*' +CLEAN.include 'lib/{2,3}.*' # clean all shipped files, that are not in git CLEAN.include( diff --git a/ext/ffi_c/AbstractMemory.c b/ext/ffi_c/AbstractMemory.c index 3cf16a7..10ddc28 100644 --- a/ext/ffi_c/AbstractMemory.c +++ b/ext/ffi_c/AbstractMemory.c @@ -150,7 +150,7 @@ memory_put_array_of_##name(VALUE self, VALUE offset, VALUE ary) \ if (likely(count > 0)) checkWrite(memory); \ checkBounds(memory, off, count * sizeof(type)); \ for (i = 0; i < count; i++) { \ - type tmp = (type) VAL(toNative(RARRAY_PTR(ary)[i]), swap); \ + type tmp = (type) VAL(toNative(RARRAY_AREF(ary, i)), swap); \ memcpy(memory->address + off + (i * sizeof(type)), &tmp, sizeof(tmp)); \ } \ return self; \ diff --git a/ext/ffi_c/ArrayType.c b/ext/ffi_c/ArrayType.c index 1d766a4..4bd77fd 100644 --- a/ext/ffi_c/ArrayType.c +++ b/ext/ffi_c/ArrayType.c @@ -29,11 +29,13 @@ #include <ruby.h> #include <ffi.h> +#include "compat.h" #include "ArrayType.h" static VALUE array_type_s_allocate(VALUE klass); static VALUE array_type_initialize(VALUE self, VALUE rbComponentType, VALUE rbLength); static void array_type_mark(void *); +static void array_type_compact(void *); static void array_type_free(void *); static size_t array_type_memsize(const void *); @@ -43,6 +45,7 @@ const rb_data_type_t rbffi_array_type_data_type = { /* extern */ .dmark = array_type_mark, .dfree = array_type_free, .dsize = array_type_memsize, + ffi_compact_callback( array_type_compact ) }, .parent = &rbffi_type_data_type, // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE() @@ -75,7 +78,14 @@ static void array_type_mark(void *data) { ArrayType *array = (ArrayType *)data; - rb_gc_mark(array->rbComponentType); + rb_gc_mark_movable(array->rbComponentType); +} + +static void +array_type_compact(void *data) +{ + ArrayType *array = (ArrayType *)data; + ffi_gc_location(array->rbComponentType); } static void diff --git a/ext/ffi_c/Buffer.c b/ext/ffi_c/Buffer.c index b3be778..0bfcc02 100644 --- a/ext/ffi_c/Buffer.c +++ b/ext/ffi_c/Buffer.c @@ -51,6 +51,7 @@ static VALUE buffer_allocate(VALUE klass); static VALUE buffer_initialize(int argc, VALUE* argv, VALUE self); static void buffer_release(void *data); static void buffer_mark(void *data); +static void buffer_compact(void *data); static VALUE buffer_free(VALUE self); static size_t allocated_buffer_memsize(const void *data); static size_t buffer_memsize(const void *data); @@ -61,6 +62,7 @@ static const rb_data_type_t buffer_data_type = { .dmark = buffer_mark, .dfree = RUBY_TYPED_DEFAULT_FREE, .dsize = buffer_memsize, + ffi_compact_callback( buffer_compact ) }, .parent = &rbffi_abstract_memory_data_type, // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE() @@ -337,7 +339,14 @@ static void buffer_mark(void *data) { Buffer *ptr = (Buffer *)data; - rb_gc_mark(ptr->data.rbParent); + rb_gc_mark_movable(ptr->data.rbParent); +} + +static void +buffer_compact(void *data) +{ + Buffer *ptr = (Buffer *)data; + ffi_gc_location(ptr->data.rbParent); } static size_t diff --git a/ext/ffi_c/DynamicLibrary.c b/ext/ffi_c/DynamicLibrary.c index 2e0bf4b..bcbc8de 100644 --- a/ext/ffi_c/DynamicLibrary.c +++ b/ext/ffi_c/DynamicLibrary.c @@ -61,6 +61,7 @@ static size_t library_memsize(const void *); static VALUE symbol_allocate(VALUE klass); static VALUE symbol_new(VALUE library, void* address, VALUE name); static void symbol_mark(void *data); +static void symbol_compact(void *data); static size_t symbol_memsize(const void *data); static const rb_data_type_t rbffi_library_data_type = { @@ -81,6 +82,7 @@ static const rb_data_type_t library_symbol_data_type = { .dmark = symbol_mark, .dfree = RUBY_TYPED_DEFAULT_FREE, .dsize = symbol_memsize, + ffi_compact_callback( symbol_compact ) }, .parent = &rbffi_pointer_data_type, // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE() @@ -223,8 +225,19 @@ dl_open(const char* name, int flags) static void dl_error(char* buf, int size) { - FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), - 0, buf, size, NULL); + // Get the last error code + DWORD error = GetLastError(); + + // Get the associated message + LPSTR message = NULL; + FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, error, 0, (LPSTR)&message, 0, NULL); + + // Update the passed in buffer + snprintf(buf, size, "Failed with error %d: %s", error, message); + + // Free the allocated message + LocalFree(message); } #endif @@ -273,8 +286,16 @@ static void symbol_mark(void *data) { LibrarySymbol *sym = (LibrarySymbol *)data; - rb_gc_mark(sym->base.rbParent); - rb_gc_mark(sym->name); + rb_gc_mark_movable(sym->base.rbParent); + rb_gc_mark_movable(sym->name); +} + +static void +symbol_compact(void *data) +{ + LibrarySymbol *sym = (LibrarySymbol *)data; + ffi_gc_location(sym->base.rbParent); + ffi_gc_location(sym->name); } static size_t diff --git a/ext/ffi_c/Function.c b/ext/ffi_c/Function.c index b73e8b7..0e68722 100644 --- a/ext/ffi_c/Function.c +++ b/ext/ffi_c/Function.c @@ -76,6 +76,7 @@ typedef struct Function_ { } Function; static void function_mark(void *data); +static void function_compact(void *data); static void function_free(void *data); static size_t function_memsize(const void *data); static VALUE function_init(VALUE self, VALUE rbFunctionInfo, VALUE rbProc); @@ -102,6 +103,7 @@ static const rb_data_type_t function_data_type = { .dmark = function_mark, .dfree = function_free, .dsize = function_memsize, + ffi_compact_callback( function_compact ) }, .parent = &rbffi_pointer_data_type, // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE() @@ -168,9 +170,18 @@ static void function_mark(void *data) { Function *fn = (Function *)data; - rb_gc_mark(fn->base.rbParent); - rb_gc_mark(fn->rbProc); - rb_gc_mark(fn->rbFunctionInfo); + rb_gc_mark_movable(fn->base.rbParent); + rb_gc_mark_movable(fn->rbProc); + rb_gc_mark_movable(fn->rbFunctionInfo); +} + +static void +function_compact(void *data) +{ + Function *fn = (Function *)data; + ffi_gc_location(fn->base.rbParent); + ffi_gc_location(fn->rbProc); + ffi_gc_location(fn->rbFunctionInfo); } static void diff --git a/ext/ffi_c/FunctionInfo.c b/ext/ffi_c/FunctionInfo.c index 6aa93d9..7f77621 100644 --- a/ext/ffi_c/FunctionInfo.c +++ b/ext/ffi_c/FunctionInfo.c @@ -52,6 +52,7 @@ static VALUE fntype_allocate(VALUE klass); static VALUE fntype_initialize(int argc, VALUE* argv, VALUE self); static void fntype_mark(void *); +static void fntype_compact(void *); static void fntype_free(void *); static size_t fntype_memsize(const void *); @@ -61,6 +62,7 @@ const rb_data_type_t rbffi_fntype_data_type = { /* extern */ .dmark = fntype_mark, .dfree = fntype_free, .dsize = fntype_memsize, + ffi_compact_callback( fntype_compact ) }, .parent = &rbffi_type_data_type, // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE() @@ -91,11 +93,27 @@ static void fntype_mark(void *data) { FunctionType *fnInfo = (FunctionType *)data; - rb_gc_mark(fnInfo->rbReturnType); - rb_gc_mark(fnInfo->rbParameterTypes); - rb_gc_mark(fnInfo->rbEnums); + rb_gc_mark_movable(fnInfo->rbReturnType); + rb_gc_mark_movable(fnInfo->rbParameterTypes); + rb_gc_mark_movable(fnInfo->rbEnums); if (fnInfo->callbackCount > 0 && fnInfo->callbackParameters != NULL) { - rb_gc_mark_locations(&fnInfo->callbackParameters[0], &fnInfo->callbackParameters[fnInfo->callbackCount]); + for (size_t index = 0; index < fnInfo->callbackCount; index++) { + rb_gc_mark_movable(fnInfo->callbackParameters[index]); + } + } +} + +static void +fntype_compact(void *data) +{ + FunctionType *fnInfo = (FunctionType *)data; + ffi_gc_location(fnInfo->rbReturnType); + ffi_gc_location(fnInfo->rbParameterTypes); + ffi_gc_location(fnInfo->rbEnums); + if (fnInfo->callbackCount > 0 && fnInfo->callbackParameters != NULL) { + for (size_t index = 0; index < fnInfo->callbackCount; index++) { + ffi_gc_location(fnInfo->callbackParameters[index]); + } } } diff --git a/ext/ffi_c/MappedType.c b/ext/ffi_c/MappedType.c index ed05c9d..b1532e1 100644 --- a/ext/ffi_c/MappedType.c +++ b/ext/ffi_c/MappedType.c @@ -31,6 +31,7 @@ #include <ffi.h> #include "rbffi.h" +#include "compat.h" #include "Type.h" #include "MappedType.h" @@ -39,6 +40,7 @@ static VALUE mapped_allocate(VALUE); static VALUE mapped_initialize(VALUE, VALUE); static void mapped_mark(void *); +static void mapped_compact(void *); static size_t mapped_memsize(const void *); static ID id_native_type, id_to_native, id_from_native; @@ -50,6 +52,7 @@ static const rb_data_type_t mapped_type_data_type = { .dmark = mapped_mark, .dfree = RUBY_TYPED_DEFAULT_FREE, .dsize = mapped_memsize, + ffi_compact_callback( mapped_compact ) }, .parent = &rbffi_type_data_type, // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE() @@ -70,7 +73,7 @@ mapped_allocate(VALUE klass) m->type = NULL; m->base.nativeType = NATIVE_MAPPED; m->base.ffiType = &ffi_type_void; - + return obj; } @@ -84,7 +87,7 @@ static VALUE mapped_initialize(VALUE self, VALUE rbConverter) { MappedType* m = NULL; - + if (!rb_respond_to(rbConverter, id_native_type)) { rb_raise(rb_eNoMethodError, "native_type method not implemented"); } @@ -114,8 +117,16 @@ static void mapped_mark(void* data) { MappedType* m = (MappedType*)data; - rb_gc_mark(m->rbType); - rb_gc_mark(m->rbConverter); + rb_gc_mark_movable(m->rbType); + rb_gc_mark_movable(m->rbConverter); +} + +static void +mapped_compact(void* data) +{ + MappedType* m = (MappedType*)data; + ffi_gc_location(m->rbType); + ffi_gc_location(m->rbConverter); } static size_t @@ -167,11 +178,11 @@ mapped_from_native(int argc, VALUE* argv, VALUE self) void rbffi_MappedType_Init(VALUE moduleFFI) { - /* + /* * Document-class: FFI::Type::Mapped < FFI::Type */ rbffi_MappedTypeClass = rb_define_class_under(rbffi_TypeClass, "Mapped", rbffi_TypeClass); - + rb_global_variable(&rbffi_MappedTypeClass); id_native_type = rb_intern("native_type"); diff --git a/ext/ffi_c/MethodHandle.c b/ext/ffi_c/MethodHandle.c index d047e10..83f7b77 100644 --- a/ext/ffi_c/MethodHandle.c +++ b/ext/ffi_c/MethodHandle.c @@ -77,7 +77,9 @@ static bool prep_trampoline(void* ctx, void* code, Closure* closure, char* errmsg, size_t errmsgsize); static long trampoline_size(void); -#if defined(__x86_64__) && (defined(__linux__) || defined(__APPLE__)) +#if defined(__x86_64__) && \ + (defined(__linux__) || defined(__APPLE__)) && \ + !USE_FFI_ALLOC # define CUSTOM_TRAMPOLINE 1 #endif diff --git a/ext/ffi_c/Pointer.c b/ext/ffi_c/Pointer.c index c926fe9..a6e8eb7 100644 --- a/ext/ffi_c/Pointer.c +++ b/ext/ffi_c/Pointer.c @@ -43,6 +43,7 @@ VALUE rbffi_NullPointerSingleton = Qnil; static void ptr_release(void *data); static void ptr_mark(void *data); +static void ptr_compact(void *data); static size_t ptr_memsize(const void *data); const rb_data_type_t rbffi_pointer_data_type = { /* extern */ @@ -51,6 +52,7 @@ const rb_data_type_t rbffi_pointer_data_type = { /* extern */ .dmark = ptr_mark, .dfree = ptr_release, .dsize = ptr_memsize, + ffi_compact_callback( ptr_compact ) }, .parent = &rbffi_abstract_memory_data_type, // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE() @@ -471,7 +473,14 @@ static void ptr_mark(void *data) { Pointer *ptr = (Pointer *)data; - rb_gc_mark(ptr->rbParent); + rb_gc_mark_movable(ptr->rbParent); +} + +static void +ptr_compact(void *data) +{ + Pointer *ptr = (Pointer *)data; + ffi_gc_location(ptr->rbParent); } static size_t diff --git a/ext/ffi_c/Struct.c b/ext/ffi_c/Struct.c index 4f57cf3..9eb10ec 100644 --- a/ext/ffi_c/Struct.c +++ b/ext/ffi_c/Struct.c @@ -62,11 +62,13 @@ typedef struct InlineArray_ { static void struct_mark(void *data); +static void struct_compact(void *data); static void struct_free(void *data); static size_t struct_memsize(const void *); static VALUE struct_class_layout(VALUE klass); static void struct_malloc(VALUE self, Struct* s); static void inline_array_mark(void *); +static void inline_array_compact(void *); static size_t inline_array_memsize(const void *); static void store_reference_value(VALUE self, StructField* f, Struct* s, VALUE value); @@ -76,6 +78,7 @@ const rb_data_type_t rbffi_struct_data_type = { /* extern */ .dmark = struct_mark, .dfree = struct_free, .dsize = struct_memsize, + ffi_compact_callback( struct_compact ) }, // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE() // macro to update VALUE references, as to trigger write barriers. @@ -129,7 +132,7 @@ struct_initialize(int argc, VALUE* argv, VALUE self) /* Call up into ruby code to adjust the layout */ if (nargs > 1) { - VALUE rbLayout = rb_funcall2(CLASS_OF(self), id_layout, (int) RARRAY_LEN(rest), RARRAY_PTR(rest)); + VALUE rbLayout = rb_apply(CLASS_OF(self), id_layout, rest); RB_OBJ_WRITE(self, &s->rbLayout, rbLayout); } else { RB_OBJ_WRITE(self, &s->rbLayout, struct_class_layout(klass)); @@ -262,10 +265,25 @@ static void struct_mark(void *data) { Struct *s = (Struct *)data; - rb_gc_mark(s->rbPointer); - rb_gc_mark(s->rbLayout); + rb_gc_mark_movable(s->rbPointer); + rb_gc_mark_movable(s->rbLayout); if (s->rbReferences != NULL) { - rb_gc_mark_locations(&s->rbReferences[0], &s->rbReferences[s->layout->referenceFieldCount]); + for (size_t index = 0; index < s->layout->referenceFieldCount; index++) { + rb_gc_mark_movable(s->rbReferences[index]); + } + } +} + +static void +struct_compact(void *data) +{ + Struct *s = (Struct *)data; + ffi_gc_location(s->rbPointer); + ffi_gc_location(s->rbLayout); + if (s->rbReferences != NULL) { + for (size_t index = 0; index < s->layout->referenceFieldCount; index++) { + ffi_gc_location(s->rbReferences[index]); + } } } @@ -522,6 +540,7 @@ static const rb_data_type_t inline_array_data_type = { .dmark = inline_array_mark, .dfree = RUBY_TYPED_DEFAULT_FREE, .dsize = inline_array_memsize, + ffi_compact_callback( inline_array_compact ) }, // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE() // macro to update VALUE references, as to trigger write barriers. @@ -545,8 +564,16 @@ static void inline_array_mark(void *data) { InlineArray *array = (InlineArray *)data; - rb_gc_mark(array->rbField); - rb_gc_mark(array->rbMemory); + rb_gc_mark_movable(array->rbField); + rb_gc_mark_movable(array->rbMemory); +} + +static void +inline_array_compact(void *data) +{ + InlineArray *array = (InlineArray *)data; + ffi_gc_location(array->rbField); + ffi_gc_location(array->rbMemory); } static size_t diff --git a/ext/ffi_c/StructByValue.c b/ext/ffi_c/StructByValue.c index e2c589d..94061f3 100644 --- a/ext/ffi_c/StructByValue.c +++ b/ext/ffi_c/StructByValue.c @@ -50,6 +50,7 @@ static VALUE sbv_allocate(VALUE); static VALUE sbv_initialize(VALUE, VALUE); static void sbv_mark(void *); +static void sbv_compact(void *); static void sbv_free(void *); static size_t sbv_memsize(const void *); @@ -61,6 +62,7 @@ static const rb_data_type_t sbv_type_data_type = { .dmark = sbv_mark, .dfree = sbv_free, .dsize = sbv_memsize, + ffi_compact_callback( sbv_compact ) }, .parent = &rbffi_type_data_type, // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE() @@ -106,7 +108,7 @@ sbv_initialize(VALUE self, VALUE rbStructClass) /* We can just use everything from the ffi_type directly */ *sbv->base.ffiType = *layout->base.ffiType; - + return self; } @@ -114,8 +116,16 @@ static void sbv_mark(void *data) { StructByValue *sbv = (StructByValue *)data; - rb_gc_mark(sbv->rbStructClass); - rb_gc_mark(sbv->rbStructLayout); + rb_gc_mark_movable(sbv->rbStructClass); + rb_gc_mark_movable(sbv->rbStructLayout); +} + +static void +sbv_compact(void *data) +{ + StructByValue *sbv = (StructByValue *)data; + ffi_gc_location(sbv->rbStructClass); + ffi_gc_location(sbv->rbStructLayout); } static void diff --git a/ext/ffi_c/StructLayout.c b/ext/ffi_c/StructLayout.c index f04b11f..548ddb5 100644 --- a/ext/ffi_c/StructLayout.c +++ b/ext/ffi_c/StructLayout.c @@ -52,9 +52,11 @@ #define FFI_ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1) static void struct_layout_mark(void *); +static void struct_layout_compact(void *); static void struct_layout_free(void *); static size_t struct_layout_memsize(const void *); static void struct_field_mark(void *); +static void struct_field_compact(void *); static size_t struct_field_memsize(const void *); VALUE rbffi_StructLayoutFieldClass = Qnil; @@ -70,6 +72,7 @@ const rb_data_type_t rbffi_struct_layout_data_type = { /* extern */ .dmark = struct_layout_mark, .dfree = struct_layout_free, .dsize = struct_layout_memsize, + ffi_compact_callback( struct_layout_compact ) }, .parent = &rbffi_type_data_type, // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE() @@ -83,6 +86,7 @@ const rb_data_type_t rbffi_struct_field_data_type = { /* extern */ .dmark = struct_field_mark, .dfree = RUBY_TYPED_DEFAULT_FREE, .dsize = struct_field_memsize, + ffi_compact_callback( struct_field_compact ) }, .parent = &rbffi_type_data_type, // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE() @@ -107,8 +111,16 @@ static void struct_field_mark(void *data) { StructField *f = (StructField *)data; - rb_gc_mark(f->rbType); - rb_gc_mark(f->rbName); + rb_gc_mark_movable(f->rbType); + rb_gc_mark_movable(f->rbName); +} + +static void +struct_field_compact(void *data) +{ + StructField *f = (StructField *)data; + ffi_gc_location(f->rbType); + ffi_gc_location(f->rbName); } static size_t @@ -628,12 +640,22 @@ static void struct_layout_mark(void *data) { StructLayout *layout = (StructLayout *)data; - rb_gc_mark(layout->rbFieldMap); - rb_gc_mark(layout->rbFieldNames); - rb_gc_mark(layout->rbFields); - for (size_t index = 0; index < FIELD_CACHE_ROWS; index++) { - rb_gc_mark(layout->cache_row[index].fieldName); - } + rb_gc_mark_movable(layout->rbFieldMap); + rb_gc_mark_movable(layout->rbFieldNames); + rb_gc_mark_movable(layout->rbFields); + /* The values stored in layout->cache_row.fieldName are primary stored in layout->rbFieldMap and are marked there */ +} + +static void +struct_layout_compact(void *data) +{ + StructLayout *layout = (StructLayout *)data; + ffi_gc_location(layout->rbFieldMap); + ffi_gc_location(layout->rbFieldNames); + ffi_gc_location(layout->rbFields); + + /* Clear the cache, to be safe from changes of fieldName VALUE by GC.compact */ + memset(&layout->cache_row, 0, sizeof(layout->cache_row)); } static void @@ -646,6 +668,7 @@ struct_layout_free(void *data) xfree(layout); } + static size_t struct_layout_memsize(const void * data) { diff --git a/ext/ffi_c/Type.c b/ext/ffi_c/Type.c index 6089a14..194c81e 100644 --- a/ext/ffi_c/Type.c +++ b/ext/ffi_c/Type.c @@ -14,7 +14,7 @@ * * Neither the name of the Ruby FFI project nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -52,8 +52,8 @@ VALUE rbffi_TypeClass = Qnil; static VALUE classBuiltinType = Qnil; static VALUE moduleNativeType = Qnil; -static VALUE typeMap = Qnil, sizeMap = Qnil; -static ID id_find_type = 0, id_type_size = 0, id_size = 0; +static VALUE typeMap = Qnil; +static ID id_type_size = 0, id_size = 0; const rb_data_type_t rbffi_type_data_type = { /* extern */ .wrap_struct_name = "FFI::Type", @@ -121,7 +121,7 @@ type_initialize(VALUE self, VALUE value) } else { rb_raise(rb_eArgError, "wrong type"); } - + return self; } @@ -217,13 +217,13 @@ int rbffi_type_size(VALUE type) { int t = TYPE(type); - + if (t == T_FIXNUM || t == T_BIGNUM) { return NUM2INT(type); - + } else if (t == T_SYMBOL) { /* - * Try looking up directly in the type and size maps + * Try looking up directly in the type map */ VALUE nType; if ((nType = rb_hash_lookup(typeMap, type)) != Qnil) { @@ -231,7 +231,7 @@ rbffi_type_size(VALUE type) Type* type; TypedData_Get_Struct(nType, Type, &rbffi_type_data_type, type); return (int) type->ffiType->size; - + } else if (rb_respond_to(nType, id_size)) { return NUM2INT(rb_funcall2(nType, id_size, 0, NULL)); } @@ -239,7 +239,7 @@ rbffi_type_size(VALUE type) /* Not found - call up to the ruby version to resolve */ return NUM2INT(rb_funcall2(rbffi_FFIModule, id_type_size, 1, &type)); - + } else { return NUM2INT(rb_funcall2(type, id_size, 0, NULL)); } @@ -251,14 +251,14 @@ rbffi_Type_Lookup(VALUE name) int t = TYPE(name); if (t == T_SYMBOL || t == T_STRING) { /* - * Try looking up directly in the type Map + * Try looking up directly in the type map */ VALUE nType; if ((nType = rb_hash_lookup(typeMap, name)) != Qnil && rb_obj_is_kind_of(nType, rbffi_TypeClass)) { return nType; } } else if (rb_obj_is_kind_of(name, rbffi_TypeClass)) { - + return name; } @@ -282,10 +282,7 @@ rbffi_Type_Init(VALUE moduleFFI) * Document-constant: FFI::TypeDefs */ rb_define_const(moduleFFI, "TypeDefs", typeMap = rb_hash_new()); - rb_define_const(moduleFFI, "SizeTypes", sizeMap = rb_hash_new()); rb_global_variable(&typeMap); - rb_global_variable(&sizeMap); - id_find_type = rb_intern("find_type"); id_type_size = rb_intern("type_size"); id_size = rb_intern("size"); @@ -328,7 +325,7 @@ rbffi_Type_Init(VALUE moduleFFI) * * BUFFER_OUT * * VARARGS (function takes a variable number of arguments) * - * All these constants are exported to {FFI} module prefixed with "TYPE_". + * All these constants are exported to {FFI} module prefixed with "TYPE_". * They are objets from {FFI::Type::Builtin} class. */ moduleNativeType = rb_define_module_under(moduleFFI, "NativeType"); @@ -349,7 +346,7 @@ rbffi_Type_Init(VALUE moduleFFI) /* Make Type::Builtin non-allocatable */ rb_undef_method(CLASS_OF(classBuiltinType), "new"); rb_define_method(classBuiltinType, "inspect", builtin_type_inspect, 0); - + rb_global_variable(&rbffi_TypeClass); rb_global_variable(&classBuiltinType); diff --git a/ext/ffi_c/Variadic.c b/ext/ffi_c/Variadic.c index 04efd24..a255969 100644 --- a/ext/ffi_c/Variadic.c +++ b/ext/ffi_c/Variadic.c @@ -66,6 +66,7 @@ static VALUE variadic_allocate(VALUE klass); static VALUE variadic_initialize(VALUE self, VALUE rbFunction, VALUE rbParameterTypes, VALUE rbReturnType, VALUE options); static void variadic_mark(void *); +static void variadic_compact(void *); static size_t variadic_memsize(const void *); static VALUE classVariadicInvoker = Qnil; @@ -76,6 +77,7 @@ static const rb_data_type_t variadic_data_type = { .dmark = variadic_mark, .dfree = RUBY_TYPED_DEFAULT_FREE, .dsize = variadic_memsize, + ffi_compact_callback( variadic_compact ) }, // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE() // macro to update VALUE references, as to trigger write barriers. @@ -101,9 +103,18 @@ static void variadic_mark(void *data) { VariadicInvoker *invoker = (VariadicInvoker *)data; - rb_gc_mark(invoker->rbEnums); - rb_gc_mark(invoker->rbAddress); - rb_gc_mark(invoker->rbReturnType); + rb_gc_mark_movable(invoker->rbEnums); + rb_gc_mark_movable(invoker->rbAddress); + rb_gc_mark_movable(invoker->rbReturnType); +} + +static void +variadic_compact(void *data) +{ + VariadicInvoker *invoker = (VariadicInvoker *)data; + ffi_gc_location(invoker->rbEnums); + ffi_gc_location(invoker->rbAddress); + ffi_gc_location(invoker->rbReturnType); } static size_t diff --git a/ext/ffi_c/compat.h b/ext/ffi_c/compat.h index 3f7bbae..856836f 100644 --- a/ext/ffi_c/compat.h +++ b/ext/ffi_c/compat.h @@ -32,26 +32,6 @@ #include <ruby.h> -#ifndef RARRAY_LEN -# define RARRAY_LEN(ary) RARRAY(ary)->len -#endif - -#ifndef RARRAY_PTR -# define RARRAY_PTR(ary) RARRAY(ary)->ptr -#endif - -#ifndef RSTRING_LEN -# define RSTRING_LEN(s) RSTRING(s)->len -#endif - -#ifndef RSTRING_PTR -# define RSTRING_PTR(s) RSTRING(s)->ptr -#endif - -#ifndef NUM2ULL -# define NUM2ULL(x) rb_num2ull((VALUE)x) -#endif - #ifndef roundup # define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) #endif @@ -75,8 +55,14 @@ # define MIN(a, b) ((a) < (b) ? (a) : (b)) #endif -#ifndef RB_GC_GUARD -# define RB_GC_GUARD(x) (x) + +#ifdef HAVE_RB_GC_MARK_MOVABLE +#define ffi_compact_callback(x) .dcompact = (x), +#define ffi_gc_location(x) x = rb_gc_location(x) +#else +#define rb_gc_mark_movable(x) rb_gc_mark(x) +#define ffi_compact_callback(x) +#define ffi_gc_location(x) #endif #endif /* RBFFI_COMPAT_H */ diff --git a/ext/ffi_c/extconf.rb b/ext/ffi_c/extconf.rb index b5bdc05..b3eb020 100755 --- a/ext/ffi_c/extconf.rb +++ b/ext/ffi_c/extconf.rb @@ -57,6 +57,8 @@ if RUBY_ENGINE == 'ruby' || RUBY_ENGINE == 'rbx' append_ldflags "-Wl,--exclude-libs,ALL" end + have_func 'rb_gc_mark_movable' # since ruby-2.7 + # Some linux archs need explicit linking to pthread, see https://github.com/ffi/ffi/issues/893 append_ldflags "-pthread" diff --git a/ext/ffi_c/libffi b/ext/ffi_c/libffi -Subproject 5c63b463b87d3c06102a4a7f05f395929d9ea79 +Subproject ac598b7f5272d536b75f4b3833a4610cf4cd940 diff --git a/lib/ffi/platform/sw_64-linux/types.conf b/lib/ffi/platform/sw_64-linux/types.conf new file mode 100644 index 0000000..aa8716d --- /dev/null +++ b/lib/ffi/platform/sw_64-linux/types.conf @@ -0,0 +1,141 @@ +rbx.platform.typedef.*__caddr_t = char +rbx.platform.typedef.__blkcnt64_t = long +rbx.platform.typedef.__blkcnt_t = long +rbx.platform.typedef.__blksize_t = int +rbx.platform.typedef.__clock_t = long +rbx.platform.typedef.__clockid_t = int +rbx.platform.typedef.__daddr_t = int +rbx.platform.typedef.__dev_t = ulong +rbx.platform.typedef.__fd_mask = long +rbx.platform.typedef.__fsblkcnt64_t = ulong +rbx.platform.typedef.__fsblkcnt_t = ulong +rbx.platform.typedef.__fsfilcnt64_t = ulong +rbx.platform.typedef.__fsfilcnt_t = ulong +rbx.platform.typedef.__fsword_t = long +rbx.platform.typedef.__gid_t = uint +rbx.platform.typedef.__id_t = uint +rbx.platform.typedef.__ino64_t = ulong +rbx.platform.typedef.__ino_t = ulong +rbx.platform.typedef.__int16_t = short +rbx.platform.typedef.__int32_t = int +rbx.platform.typedef.__int64_t = long +rbx.platform.typedef.__int8_t = char +rbx.platform.typedef.__int_least16_t = short +rbx.platform.typedef.__int_least32_t = int +rbx.platform.typedef.__int_least64_t = long +rbx.platform.typedef.__int_least8_t = char +rbx.platform.typedef.__intmax_t = long +rbx.platform.typedef.__intptr_t = long +rbx.platform.typedef.__key_t = int +rbx.platform.typedef.__loff_t = long +rbx.platform.typedef.__mode_t = uint +rbx.platform.typedef.__nlink_t = uint +rbx.platform.typedef.__off64_t = long +rbx.platform.typedef.__off_t = long +rbx.platform.typedef.__pid_t = int +rbx.platform.typedef.__priority_which_t = int +rbx.platform.typedef.__quad_t = long +rbx.platform.typedef.__rlim64_t = ulong +rbx.platform.typedef.__rlim_t = ulong +rbx.platform.typedef.__rlimit_resource_t = int +rbx.platform.typedef.__rusage_who_t = int +rbx.platform.typedef.__sig_atomic_t = int +rbx.platform.typedef.__socklen_t = uint +rbx.platform.typedef.__ssize_t = long +rbx.platform.typedef.__suseconds_t = long +rbx.platform.typedef.__syscall_slong_t = long +rbx.platform.typedef.__syscall_ulong_t = ulong +rbx.platform.typedef.__time_t = long +rbx.platform.typedef.__timer_t = pointer +rbx.platform.typedef.__u_char = uchar +rbx.platform.typedef.__u_int = uint +rbx.platform.typedef.__u_long = ulong +rbx.platform.typedef.__u_quad_t = ulong +rbx.platform.typedef.__u_short = ushort +rbx.platform.typedef.__uid_t = uint +rbx.platform.typedef.__uint16_t = ushort +rbx.platform.typedef.__uint32_t = uint +rbx.platform.typedef.__uint64_t = ulong +rbx.platform.typedef.__uint8_t = uchar +rbx.platform.typedef.__uint_least16_t = ushort +rbx.platform.typedef.__uint_least32_t = uint +rbx.platform.typedef.__uint_least64_t = ulong +rbx.platform.typedef.__uint_least8_t = uchar +rbx.platform.typedef.__uintmax_t = ulong +rbx.platform.typedef.__useconds_t = uint +rbx.platform.typedef.blkcnt_t = long +rbx.platform.typedef.blksize_t = int +rbx.platform.typedef.clock_t = long +rbx.platform.typedef.clockid_t = int +rbx.platform.typedef.daddr_t = int +rbx.platform.typedef.dev_t = ulong +rbx.platform.typedef.fd_mask = long +rbx.platform.typedef.fsblkcnt_t = ulong +rbx.platform.typedef.fsfilcnt_t = ulong +rbx.platform.typedef.gid_t = uint +rbx.platform.typedef.id_t = uint +rbx.platform.typedef.in_addr_t = uint +rbx.platform.typedef.in_port_t = ushort +rbx.platform.typedef.ino_t = ulong +rbx.platform.typedef.int16_t = short +rbx.platform.typedef.int32_t = int +rbx.platform.typedef.int64_t = long +rbx.platform.typedef.int8_t = char +rbx.platform.typedef.int_fast16_t = long +rbx.platform.typedef.int_fast32_t = long +rbx.platform.typedef.int_fast64_t = long +rbx.platform.typedef.int_fast8_t = char +rbx.platform.typedef.int_least16_t = short +rbx.platform.typedef.int_least32_t = int +rbx.platform.typedef.int_least64_t = long +rbx.platform.typedef.int_least8_t = char +rbx.platform.typedef.intmax_t = long +rbx.platform.typedef.intptr_t = long +rbx.platform.typedef.key_t = int +rbx.platform.typedef.loff_t = long +rbx.platform.typedef.mode_t = uint +rbx.platform.typedef.nlink_t = uint +rbx.platform.typedef.off_t = long +rbx.platform.typedef.pid_t = int +rbx.platform.typedef.pthread_key_t = uint +rbx.platform.typedef.pthread_once_t = int +rbx.platform.typedef.pthread_t = ulong +rbx.platform.typedef.ptrdiff_t = long +rbx.platform.typedef.quad_t = long +rbx.platform.typedef.register_t = long +rbx.platform.typedef.rlim_t = ulong +rbx.platform.typedef.sa_family_t = ushort +rbx.platform.typedef.size_t = ulong +rbx.platform.typedef.socklen_t = uint +rbx.platform.typedef.ssize_t = long +rbx.platform.typedef.suseconds_t = long +rbx.platform.typedef.time_t = long +rbx.platform.typedef.timer_t = pointer +rbx.platform.typedef.u_char = uchar +rbx.platform.typedef.u_int = uint +rbx.platform.typedef.u_int16_t = ushort +rbx.platform.typedef.u_int32_t = uint +rbx.platform.typedef.u_int64_t = ulong_long +rbx.platform.typedef.u_int8_t = uchar +rbx.platform.typedef.u_long = ulong +rbx.platform.typedef.u_quad_t = ulong +rbx.platform.typedef.u_short = ushort +rbx.platform.typedef.uid_t = uint +rbx.platform.typedef.uint = uint +rbx.platform.typedef.uint16_t = ushort +rbx.platform.typedef.uint32_t = uint +rbx.platform.typedef.uint64_t = ulong +rbx.platform.typedef.uint8_t = uchar +rbx.platform.typedef.uint_fast16_t = ulong +rbx.platform.typedef.uint_fast32_t = ulong +rbx.platform.typedef.uint_fast64_t = ulong +rbx.platform.typedef.uint_fast8_t = uchar +rbx.platform.typedef.uint_least16_t = ushort +rbx.platform.typedef.uint_least32_t = uint +rbx.platform.typedef.uint_least64_t = ulong +rbx.platform.typedef.uint_least8_t = uchar +rbx.platform.typedef.uintmax_t = ulong +rbx.platform.typedef.uintptr_t = ulong +rbx.platform.typedef.ulong = ulong +rbx.platform.typedef.ushort = ushort +rbx.platform.typedef.wchar_t = int diff --git a/spec/ffi/function_spec.rb b/spec/ffi/function_spec.rb index a1a50f3..7f90ea3 100644 --- a/spec/ffi/function_spec.rb +++ b/spec/ffi/function_spec.rb @@ -59,6 +59,16 @@ describe FFI::Function do expect(Foo.add(10, 10)).to eq(20) end + it 'can be attached to two modules' do + module Foo1; end + module Foo2; end + fp = FFI::Function.new(:int, [:int, :int], @libtest.find_function('testAdd')) + fp.attach(Foo1, 'add') + fp.attach(Foo2, 'add') + expect(Foo1.add(11, 11)).to eq(22) + expect(Foo2.add(12, 12)).to eq(24) + end + it 'can be used to extend an object' do fp = FFI::Function.new(:int, [:int, :int], @libtest.find_function('testAdd')) foo = Object.new |