summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml4
-rw-r--r--.gitignore13
-rw-r--r--ext/ffi_c/AbstractMemory.c2
-rw-r--r--ext/ffi_c/DynamicLibrary.c15
-rw-r--r--ext/ffi_c/Struct.c12
-rw-r--r--ext/ffi_c/Struct.h3
-rw-r--r--ext/ffi_c/compat.h23
-rwxr-xr-xext/ffi_c/extconf.rb1
-rw-r--r--lib/ffi/autopointer.rb24
-rw-r--r--lib/ffi/managedstruct.rb2
-rw-r--r--lib/ffi/platform/hppa1.1-linux/types.conf178
-rw-r--r--lib/ffi/platform/hppa2.0-linux/types.conf178
-rw-r--r--spec/ffi/fixtures/ClosureTest.c12
-rw-r--r--spec/ffi/fixtures/PipeHelperWindows.c4
-rw-r--r--spec/ffi/fixtures/PointerTest.c2
-rw-r--r--spec/ffi/gc_compact_spec.rb66
-rw-r--r--spec/ffi/managed_struct_spec.rb2
-rw-r--r--spec/ffi/pointer_spec.rb11
-rw-r--r--spec/ffi/spec_helper.rb2
19 files changed, 476 insertions, 78 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b9e87d6..fc48721 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -32,7 +32,7 @@ jobs:
env:
# work around misconfiguration of libffi on MacOS with homebrew
PKG_CONFIG_PATH: ${{ env.PKG_CONFIG_PATH }}:/usr/local/opt/libffi/lib/pkgconfig
- - run: bundle exec rake test
+ - run: bundle exec rake test FFI_TEST_GC=true
- run: bundle exec rake types_conf && git --no-pager diff
specs:
@@ -60,7 +60,7 @@ jobs:
- run: bundle exec rake libffi
- run: bundle exec rake compile
- - run: bundle exec rake test
+ - run: bundle exec rake test FFI_TEST_GC=true
- run: bundle exec rake bench:all
if: ${{ matrix.ruby != 'truffleruby-head' && matrix.ruby != 'jruby-head' }}
diff --git a/.gitignore b/.gitignore
index ff9d895..93c98ce 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,14 +12,17 @@ build
*.so
*.[oa]
core
-lib/ffi/types.conf
-lib/ffi_c.bundle
-lib/ffi_c.so
+/lib/ffi/types.conf
+/lib/ffi_c.bundle
+/lib/ffi_c.so
vendor
.bundle
Gemfile.lock
types_log
*.gem
embed-test.rb.log
-spec/ffi/embed-test/ext/Makefile
-spec/ffi/embed-test/ext/embed_test.bundle
+/spec/ffi/embed-test/ext/Makefile
+/spec/ffi/embed-test/ext/embed_test.bundle
+/ext/ffi_c/Makefile
+/ext/ffi_c/extconf.h
+/ext/ffi_c/mkmf.log
diff --git a/ext/ffi_c/AbstractMemory.c b/ext/ffi_c/AbstractMemory.c
index 3b076bb..49da32e 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/DynamicLibrary.c b/ext/ffi_c/DynamicLibrary.c
index 1d83940..9096e74 100644
--- a/ext/ffi_c/DynamicLibrary.c
+++ b/ext/ffi_c/DynamicLibrary.c
@@ -227,8 +227,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
diff --git a/ext/ffi_c/Struct.c b/ext/ffi_c/Struct.c
index 99b164d..0fdba71 100644
--- a/ext/ffi_c/Struct.c
+++ b/ext/ffi_c/Struct.c
@@ -132,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));
@@ -356,10 +356,7 @@ struct_aref(VALUE self, VALUE fieldName)
s = struct_validate(self);
f = struct_field(s, fieldName);
- if (f->get != NULL) {
- return (*f->get)(f, s);
-
- } else if (f->memoryOp != NULL) {
+ if (f->memoryOp != NULL) {
return (*f->memoryOp->get)(s->pointer, f->offset);
} else {
@@ -386,10 +383,7 @@ struct_aset(VALUE self, VALUE fieldName, VALUE value)
s = struct_validate(self);
f = struct_field(s, fieldName);
- if (f->put != NULL) {
- (*f->put)(f, s, value);
-
- } else if (f->memoryOp != NULL) {
+ if (f->memoryOp != NULL) {
(*f->memoryOp->put)(s->pointer, f->offset, value);
diff --git a/ext/ffi_c/Struct.h b/ext/ffi_c/Struct.h
index 8e9491b..b86607d 100644
--- a/ext/ffi_c/Struct.h
+++ b/ext/ffi_c/Struct.h
@@ -59,9 +59,6 @@ extern "C" {
VALUE rbType;
VALUE rbName;
- VALUE (*get)(StructField* field, Struct* s);
- void (*put)(StructField* field, Struct* s, VALUE value);
-
MemoryOp* memoryOp;
};
diff --git a/ext/ffi_c/compat.h b/ext/ffi_c/compat.h
index 27a99be..a1be55d 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,9 +55,6 @@
# define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
-#ifndef RB_GC_GUARD
-# define RB_GC_GUARD(x) (x)
-#endif
/* For compatibility with ruby < 2.7 */
diff --git a/ext/ffi_c/extconf.rb b/ext/ffi_c/extconf.rb
index a03b433..b3eb020 100755
--- a/ext/ffi_c/extconf.rb
+++ b/ext/ffi_c/extconf.rb
@@ -63,6 +63,7 @@ if RUBY_ENGINE == 'ruby' || RUBY_ENGINE == 'rbx'
append_ldflags "-pthread"
ffi_alloc_default = RbConfig::CONFIG['host_os'] =~ /darwin/i && RbConfig::CONFIG['host'] =~ /arm|aarch64/i
+ ffi_alloc_default = ffi_alloc_default || RbConfig::CONFIG['host'] =~ /hppa/i
if enable_config('libffi-alloc', ffi_alloc_default)
$defs << "-DUSE_FFI_ALLOC"
end
diff --git a/lib/ffi/autopointer.rb b/lib/ffi/autopointer.rb
index bd4c911..bbcb6db 100644
--- a/lib/ffi/autopointer.rb
+++ b/lib/ffi/autopointer.rb
@@ -84,13 +84,13 @@ module FFI
if not proc.respond_to?(:call)
raise RuntimeError.new("proc must be callable")
end
- CallableReleaser.new(ptr, proc)
+ Releaser.new(ptr, proc)
else
- if not self.class.respond_to?(:release)
+ if not self.class.respond_to?(:release, true)
raise RuntimeError.new("no release method defined")
end
- DefaultReleaser.new(ptr, self.class)
+ Releaser.new(ptr, self.class.method(:release))
end
ObjectSpace.define_finalizer(self, @releaser)
@@ -150,23 +150,7 @@ module FFI
def call(*args)
release(@ptr) if @autorelease && @ptr
end
- end
-
- # DefaultReleaser is a {Releaser} used when an {AutoPointer} is defined
- # without Proc or Method. In this case, the pointer to release must be of
- # a class derived from AutoPointer with a {release} class method.
- class DefaultReleaser < Releaser
- # @param [Pointer] ptr
- # @return [nil]
- # Release +ptr+ using the {release} class method of its class.
- def release(ptr)
- @proc.release(ptr)
- end
- end
- # CallableReleaser is a {Releaser} used when an {AutoPointer} is defined with a
- # Proc or a Method.
- class CallableReleaser < Releaser
# Release +ptr+ by using Proc or Method defined at +ptr+
# {AutoPointer#initialize initialization}.
#
@@ -183,7 +167,7 @@ module FFI
# @return [Type::POINTER]
# @raise {RuntimeError} if class does not implement a +#release+ method
def self.native_type
- if not self.respond_to?(:release)
+ if not self.respond_to?(:release, true)
raise RuntimeError.new("no release method defined for #{self.inspect}")
end
Type::POINTER
diff --git a/lib/ffi/managedstruct.rb b/lib/ffi/managedstruct.rb
index b5ec8a3..5d243e5 100644
--- a/lib/ffi/managedstruct.rb
+++ b/lib/ffi/managedstruct.rb
@@ -75,7 +75,7 @@ module FFI
# @overload initialize
# A new instance of FFI::ManagedStruct.
def initialize(pointer=nil)
- raise NoMethodError, "release() not implemented for class #{self}" unless self.class.respond_to? :release
+ raise NoMethodError, "release() not implemented for class #{self}" unless self.class.respond_to?(:release, true)
raise ArgumentError, "Must supply a pointer to memory for the Struct" unless pointer
super AutoPointer.new(pointer, self.class.method(:release))
end
diff --git a/lib/ffi/platform/hppa1.1-linux/types.conf b/lib/ffi/platform/hppa1.1-linux/types.conf
new file mode 100644
index 0000000..c8a8141
--- /dev/null
+++ b/lib/ffi/platform/hppa1.1-linux/types.conf
@@ -0,0 +1,178 @@
+rbx.platform.typedef.*__caddr_t = char
+rbx.platform.typedef.__blkcnt64_t = long_long
+rbx.platform.typedef.__blkcnt_t = long
+rbx.platform.typedef.__blksize_t = long
+rbx.platform.typedef.__clock_t = long
+rbx.platform.typedef.__clockid_t = int
+rbx.platform.typedef.__daddr_t = int
+rbx.platform.typedef.__dev_t = ulong_long
+rbx.platform.typedef.__fd_mask = long
+rbx.platform.typedef.__fsblkcnt64_t = ulong_long
+rbx.platform.typedef.__fsblkcnt_t = ulong
+rbx.platform.typedef.__fsfilcnt64_t = ulong_long
+rbx.platform.typedef.__fsfilcnt_t = ulong
+rbx.platform.typedef.__fsword_t = int
+rbx.platform.typedef.__gid_t = uint
+rbx.platform.typedef.__id_t = uint
+rbx.platform.typedef.__ino64_t = ulong_long
+rbx.platform.typedef.__ino_t = ulong
+rbx.platform.typedef.__int16_t = short
+rbx.platform.typedef.__int32_t = int
+rbx.platform.typedef.__int64_t = long_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_long
+rbx.platform.typedef.__int_least8_t = char
+rbx.platform.typedef.__intmax_t = long_long
+rbx.platform.typedef.__intptr_t = int
+rbx.platform.typedef.__kernel_caddr_t = string
+rbx.platform.typedef.__kernel_clock_t = long
+rbx.platform.typedef.__kernel_clockid_t = int
+rbx.platform.typedef.__kernel_daddr_t = int
+rbx.platform.typedef.__kernel_gid16_t = ushort
+rbx.platform.typedef.__kernel_gid32_t = uint
+rbx.platform.typedef.__kernel_gid_t = uint
+rbx.platform.typedef.__kernel_ino64_t = ulong_long
+rbx.platform.typedef.__kernel_ino_t = ulong
+rbx.platform.typedef.__kernel_ipc_pid_t = ushort
+rbx.platform.typedef.__kernel_key_t = int
+rbx.platform.typedef.__kernel_loff_t = long_long
+rbx.platform.typedef.__kernel_long_t = long
+rbx.platform.typedef.__kernel_mode_t = ushort
+rbx.platform.typedef.__kernel_mqd_t = int
+rbx.platform.typedef.__kernel_off64_t = long_long
+rbx.platform.typedef.__kernel_off_t = long
+rbx.platform.typedef.__kernel_old_dev_t = uint
+rbx.platform.typedef.__kernel_old_gid_t = uint
+rbx.platform.typedef.__kernel_old_time_t = long
+rbx.platform.typedef.__kernel_old_uid_t = uint
+rbx.platform.typedef.__kernel_pid_t = int
+rbx.platform.typedef.__kernel_ptrdiff_t = int
+rbx.platform.typedef.__kernel_size_t = uint
+rbx.platform.typedef.__kernel_ssize_t = int
+rbx.platform.typedef.__kernel_suseconds_t = long
+rbx.platform.typedef.__kernel_time64_t = long_long
+rbx.platform.typedef.__kernel_time_t = long
+rbx.platform.typedef.__kernel_timer_t = int
+rbx.platform.typedef.__kernel_uid16_t = ushort
+rbx.platform.typedef.__kernel_uid32_t = uint
+rbx.platform.typedef.__kernel_uid_t = uint
+rbx.platform.typedef.__kernel_ulong_t = ulong
+rbx.platform.typedef.__key_t = int
+rbx.platform.typedef.__loff_t = long_long
+rbx.platform.typedef.__mode_t = uint
+rbx.platform.typedef.__nlink_t = uint
+rbx.platform.typedef.__off64_t = long_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_long
+rbx.platform.typedef.__rlim64_t = ulong_long
+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 = int
+rbx.platform.typedef.__suseconds64_t = long_long
+rbx.platform.typedef.__suseconds_t = long
+rbx.platform.typedef.__syscall_slong_t = long
+rbx.platform.typedef.__syscall_ulong_t = ulong
+rbx.platform.typedef.__thrd_t = ulong
+rbx.platform.typedef.__time64_t = long_long
+rbx.platform.typedef.__time_t = long
+rbx.platform.typedef.__timer_t = pointer
+rbx.platform.typedef.__tss_t = uint
+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_long
+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_long
+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_long
+rbx.platform.typedef.__uint_least8_t = uchar
+rbx.platform.typedef.__uintmax_t = ulong_long
+rbx.platform.typedef.__useconds_t = uint
+rbx.platform.typedef.blkcnt_t = long_long
+rbx.platform.typedef.blksize_t = long
+rbx.platform.typedef.clock_t = long
+rbx.platform.typedef.clockid_t = int
+rbx.platform.typedef.daddr_t = int
+rbx.platform.typedef.dev_t = ulong_long
+rbx.platform.typedef.fd_mask = long
+rbx.platform.typedef.fsblkcnt_t = ulong_long
+rbx.platform.typedef.fsfilcnt_t = ulong_long
+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_long
+rbx.platform.typedef.int16_t = short
+rbx.platform.typedef.int32_t = int
+rbx.platform.typedef.int64_t = long_long
+rbx.platform.typedef.int8_t = char
+rbx.platform.typedef.int_fast16_t = int
+rbx.platform.typedef.int_fast32_t = int
+rbx.platform.typedef.int_fast64_t = long_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_long
+rbx.platform.typedef.int_least8_t = char
+rbx.platform.typedef.intmax_t = long_long
+rbx.platform.typedef.intptr_t = int
+rbx.platform.typedef.key_t = int
+rbx.platform.typedef.loff_t = long_long
+rbx.platform.typedef.mode_t = uint
+rbx.platform.typedef.nlink_t = uint
+rbx.platform.typedef.off_t = long_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 = int
+rbx.platform.typedef.quad_t = long_long
+rbx.platform.typedef.register_t = long
+rbx.platform.typedef.rlim_t = ulong_long
+rbx.platform.typedef.sa_family_t = ushort
+rbx.platform.typedef.size_t = uint
+rbx.platform.typedef.socklen_t = uint
+rbx.platform.typedef.ssize_t = int
+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_long
+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_long
+rbx.platform.typedef.uint8_t = uchar
+rbx.platform.typedef.uint_fast16_t = uint
+rbx.platform.typedef.uint_fast32_t = uint
+rbx.platform.typedef.uint_fast64_t = ulong_long
+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_long
+rbx.platform.typedef.uint_least8_t = uchar
+rbx.platform.typedef.uintmax_t = ulong_long
+rbx.platform.typedef.uintptr_t = uint
+rbx.platform.typedef.ulong = ulong
+rbx.platform.typedef.ushort = ushort
+rbx.platform.typedef.wchar_t = long
diff --git a/lib/ffi/platform/hppa2.0-linux/types.conf b/lib/ffi/platform/hppa2.0-linux/types.conf
new file mode 100644
index 0000000..c8a8141
--- /dev/null
+++ b/lib/ffi/platform/hppa2.0-linux/types.conf
@@ -0,0 +1,178 @@
+rbx.platform.typedef.*__caddr_t = char
+rbx.platform.typedef.__blkcnt64_t = long_long
+rbx.platform.typedef.__blkcnt_t = long
+rbx.platform.typedef.__blksize_t = long
+rbx.platform.typedef.__clock_t = long
+rbx.platform.typedef.__clockid_t = int
+rbx.platform.typedef.__daddr_t = int
+rbx.platform.typedef.__dev_t = ulong_long
+rbx.platform.typedef.__fd_mask = long
+rbx.platform.typedef.__fsblkcnt64_t = ulong_long
+rbx.platform.typedef.__fsblkcnt_t = ulong
+rbx.platform.typedef.__fsfilcnt64_t = ulong_long
+rbx.platform.typedef.__fsfilcnt_t = ulong
+rbx.platform.typedef.__fsword_t = int
+rbx.platform.typedef.__gid_t = uint
+rbx.platform.typedef.__id_t = uint
+rbx.platform.typedef.__ino64_t = ulong_long
+rbx.platform.typedef.__ino_t = ulong
+rbx.platform.typedef.__int16_t = short
+rbx.platform.typedef.__int32_t = int
+rbx.platform.typedef.__int64_t = long_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_long
+rbx.platform.typedef.__int_least8_t = char
+rbx.platform.typedef.__intmax_t = long_long
+rbx.platform.typedef.__intptr_t = int
+rbx.platform.typedef.__kernel_caddr_t = string
+rbx.platform.typedef.__kernel_clock_t = long
+rbx.platform.typedef.__kernel_clockid_t = int
+rbx.platform.typedef.__kernel_daddr_t = int
+rbx.platform.typedef.__kernel_gid16_t = ushort
+rbx.platform.typedef.__kernel_gid32_t = uint
+rbx.platform.typedef.__kernel_gid_t = uint
+rbx.platform.typedef.__kernel_ino64_t = ulong_long
+rbx.platform.typedef.__kernel_ino_t = ulong
+rbx.platform.typedef.__kernel_ipc_pid_t = ushort
+rbx.platform.typedef.__kernel_key_t = int
+rbx.platform.typedef.__kernel_loff_t = long_long
+rbx.platform.typedef.__kernel_long_t = long
+rbx.platform.typedef.__kernel_mode_t = ushort
+rbx.platform.typedef.__kernel_mqd_t = int
+rbx.platform.typedef.__kernel_off64_t = long_long
+rbx.platform.typedef.__kernel_off_t = long
+rbx.platform.typedef.__kernel_old_dev_t = uint
+rbx.platform.typedef.__kernel_old_gid_t = uint
+rbx.platform.typedef.__kernel_old_time_t = long
+rbx.platform.typedef.__kernel_old_uid_t = uint
+rbx.platform.typedef.__kernel_pid_t = int
+rbx.platform.typedef.__kernel_ptrdiff_t = int
+rbx.platform.typedef.__kernel_size_t = uint
+rbx.platform.typedef.__kernel_ssize_t = int
+rbx.platform.typedef.__kernel_suseconds_t = long
+rbx.platform.typedef.__kernel_time64_t = long_long
+rbx.platform.typedef.__kernel_time_t = long
+rbx.platform.typedef.__kernel_timer_t = int
+rbx.platform.typedef.__kernel_uid16_t = ushort
+rbx.platform.typedef.__kernel_uid32_t = uint
+rbx.platform.typedef.__kernel_uid_t = uint
+rbx.platform.typedef.__kernel_ulong_t = ulong
+rbx.platform.typedef.__key_t = int
+rbx.platform.typedef.__loff_t = long_long
+rbx.platform.typedef.__mode_t = uint
+rbx.platform.typedef.__nlink_t = uint
+rbx.platform.typedef.__off64_t = long_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_long
+rbx.platform.typedef.__rlim64_t = ulong_long
+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 = int
+rbx.platform.typedef.__suseconds64_t = long_long
+rbx.platform.typedef.__suseconds_t = long
+rbx.platform.typedef.__syscall_slong_t = long
+rbx.platform.typedef.__syscall_ulong_t = ulong
+rbx.platform.typedef.__thrd_t = ulong
+rbx.platform.typedef.__time64_t = long_long
+rbx.platform.typedef.__time_t = long
+rbx.platform.typedef.__timer_t = pointer
+rbx.platform.typedef.__tss_t = uint
+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_long
+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_long
+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_long
+rbx.platform.typedef.__uint_least8_t = uchar
+rbx.platform.typedef.__uintmax_t = ulong_long
+rbx.platform.typedef.__useconds_t = uint
+rbx.platform.typedef.blkcnt_t = long_long
+rbx.platform.typedef.blksize_t = long
+rbx.platform.typedef.clock_t = long
+rbx.platform.typedef.clockid_t = int
+rbx.platform.typedef.daddr_t = int
+rbx.platform.typedef.dev_t = ulong_long
+rbx.platform.typedef.fd_mask = long
+rbx.platform.typedef.fsblkcnt_t = ulong_long
+rbx.platform.typedef.fsfilcnt_t = ulong_long
+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_long
+rbx.platform.typedef.int16_t = short
+rbx.platform.typedef.int32_t = int
+rbx.platform.typedef.int64_t = long_long
+rbx.platform.typedef.int8_t = char
+rbx.platform.typedef.int_fast16_t = int
+rbx.platform.typedef.int_fast32_t = int
+rbx.platform.typedef.int_fast64_t = long_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_long
+rbx.platform.typedef.int_least8_t = char
+rbx.platform.typedef.intmax_t = long_long
+rbx.platform.typedef.intptr_t = int
+rbx.platform.typedef.key_t = int
+rbx.platform.typedef.loff_t = long_long
+rbx.platform.typedef.mode_t = uint
+rbx.platform.typedef.nlink_t = uint
+rbx.platform.typedef.off_t = long_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 = int
+rbx.platform.typedef.quad_t = long_long
+rbx.platform.typedef.register_t = long
+rbx.platform.typedef.rlim_t = ulong_long
+rbx.platform.typedef.sa_family_t = ushort
+rbx.platform.typedef.size_t = uint
+rbx.platform.typedef.socklen_t = uint
+rbx.platform.typedef.ssize_t = int
+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_long
+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_long
+rbx.platform.typedef.uint8_t = uchar
+rbx.platform.typedef.uint_fast16_t = uint
+rbx.platform.typedef.uint_fast32_t = uint
+rbx.platform.typedef.uint_fast64_t = ulong_long
+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_long
+rbx.platform.typedef.uint_least8_t = uchar
+rbx.platform.typedef.uintmax_t = ulong_long
+rbx.platform.typedef.uintptr_t = uint
+rbx.platform.typedef.ulong = ulong
+rbx.platform.typedef.ushort = ushort
+rbx.platform.typedef.wchar_t = long
diff --git a/spec/ffi/fixtures/ClosureTest.c b/spec/ffi/fixtures/ClosureTest.c
index 16f72c4..47273e8 100644
--- a/spec/ffi/fixtures/ClosureTest.c
+++ b/spec/ffi/fixtures/ClosureTest.c
@@ -16,10 +16,10 @@
double testClosureVrDva(double d, ...) {
va_list args;
- double (*closure)(void);
+ typedef double (*closure_fun)(void);
va_start(args, d);
- closure = va_arg(args, double (*)(void));
+ closure_fun closure = va_arg(args, closure_fun);
va_end(args);
return d + closure();
@@ -27,12 +27,12 @@ double testClosureVrDva(double d, ...) {
long testClosureVrILva(int i, long l, ...) {
va_list args;
- int (*cl1)(int);
- long (*cl2)(long);
+ typedef int (*cl1_fun)(int);
+ typedef long (*cl2_fun)(long);
va_start(args, l);
- cl1 = va_arg(args, int (*)(int));
- cl2 = va_arg(args, long (*)(long));
+ cl1_fun cl1 = va_arg(args, cl1_fun);
+ cl2_fun cl2 = va_arg(args, cl2_fun);
va_end(args);
return cl1(i) + cl2(l);
diff --git a/spec/ffi/fixtures/PipeHelperWindows.c b/spec/ffi/fixtures/PipeHelperWindows.c
index 0bdbd2e..31b4a2a 100644
--- a/spec/ffi/fixtures/PipeHelperWindows.c
+++ b/spec/ffi/fixtures/PipeHelperWindows.c
@@ -16,7 +16,7 @@ int pipeHelperCreatePipe(FD_TYPE pipefd[2])
sprintf( name, "\\\\.\\Pipe\\pipeHelper-%u-%i",
(unsigned int)GetCurrentProcessId(), pipe_idx++ );
- pipefd[0] = CreateNamedPipe( name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
+ pipefd[0] = CreateNamedPipeA( name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE | PIPE_WAIT,
1, // Number of pipes
5, // Out buffer size
@@ -26,7 +26,7 @@ int pipeHelperCreatePipe(FD_TYPE pipefd[2])
if(pipefd[0] == INVALID_HANDLE_VALUE)
return -1;
- pipefd[1] = CreateFile( name, GENERIC_WRITE, 0, NULL,
+ pipefd[1] = CreateFileA( name, GENERIC_WRITE, 0, NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
diff --git a/spec/ffi/fixtures/PointerTest.c b/spec/ffi/fixtures/PointerTest.c
index a7f392a..02dbc27 100644
--- a/spec/ffi/fixtures/PointerTest.c
+++ b/spec/ffi/fixtures/PointerTest.c
@@ -5,7 +5,9 @@
*/
#include <sys/types.h>
+#ifndef _MSC_VER
#include <sys/param.h>
+#endif
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
diff --git a/spec/ffi/gc_compact_spec.rb b/spec/ffi/gc_compact_spec.rb
new file mode 100644
index 0000000..974d7f8
--- /dev/null
+++ b/spec/ffi/gc_compact_spec.rb
@@ -0,0 +1,66 @@
+# -*- rspec -*-
+# encoding: utf-8
+#
+# Tests to verify correct implementation of compaction callbacks in rb_data_type_t definitions.
+#
+# Compaction callbacks update moved VALUEs.
+# In ruby-2.7 they are invoked only while GC.compact or GC.verify_compaction_references.
+# Ruby constants are usually moved, but local variables are not.
+#
+# Effectiveness of the tests below should be verified by commenting the compact callback out like so:
+#
+# const rb_data_type_t rbffi_struct_layout_data_type = {
+# .wrap_struct_name = "FFI::StructLayout",
+# .function = {
+# .dmark = struct_layout_mark,
+# .dfree = struct_layout_free,
+# .dsize = struct_layout_memsize,
+# # ffi_compact_callback( struct_layout_compact )
+# },
+# .parent = &rbffi_type_data_type,
+# .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
+# };
+#
+# This should result in a segmentation fault aborting the whole process.
+# Therefore the effectiveness of only one test can be verified per rspec run.
+
+require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
+
+describe "GC.compact", if: GC.respond_to?(:compact) do
+ before :all do
+
+ class St1 < FFI::Struct
+ layout :i, :int
+ end
+ ST1 = St1.new
+
+ class St2 < FFI::Struct
+ layout :i, :int
+ end
+ ST2 = St2.new
+ ST2[:i] = 6789
+
+ begin
+ # Use GC.verify_compaction_references instead of GC.compact .
+ # This has the advantage that all movable objects are actually moved.
+ # The downside is that it doubles the heap space of the Ruby process.
+ # Therefore we call it only once and do several tests afterwards.
+ GC.verify_compaction_references(toward: :empty, double_heap: true)
+ rescue NotImplementedError, NoMethodError => err
+ skip("GC.compact skipped: #{err}")
+ end
+ end
+
+ it "should compact FFI::StructLayout without field cache" do
+ expect( ST1[:i] ).to eq( 0 )
+ end
+
+ it "should compact FFI::StructLayout with field cache" do
+ expect( ST2[:i] ).to eq( 6789 )
+ end
+
+ it "should compact FFI::StructLayout::Field" do
+ l = St1.layout
+ expect( l.fields.first.type ).to eq( FFI::Type::Builtin::INT32 )
+ end
+end
diff --git a/spec/ffi/managed_struct_spec.rb b/spec/ffi/managed_struct_spec.rb
index b4e80bb..6299bdc 100644
--- a/spec/ffi/managed_struct_spec.rb
+++ b/spec/ffi/managed_struct_spec.rb
@@ -46,6 +46,8 @@ describe "Managed Struct" do
def self.release(_ptr)
@@count += 1
end
+ private_class_method :release
+
def self.wait_gc(count)
loop = 5
while loop > 0 && @@count < count
diff --git a/spec/ffi/pointer_spec.rb b/spec/ffi/pointer_spec.rb
index 880ffd3..8716d30 100644
--- a/spec/ffi/pointer_spec.rb
+++ b/spec/ffi/pointer_spec.rb
@@ -264,6 +264,7 @@ describe "AutoPointer" do
def self.release
@@count += 1 if @@count > 0
end
+ private_class_method(:release)
def self.reset
@@count = 0
end
@@ -282,10 +283,11 @@ describe "AutoPointer" do
end
class AutoPointerSubclass < FFI::AutoPointer
def self.release(ptr); end
+ private_class_method(:release)
end
# see #427
- it "cleanup via default release method", :broken => true do
+ it "cleanup via default release method", gc_dependent: true do
expect(AutoPointerSubclass).to receive(:release).at_least(loop_count-wiggle_room).times
AutoPointerTestHelper.reset
loop_count.times do
@@ -298,7 +300,7 @@ describe "AutoPointer" do
end
# see #427
- it "cleanup when passed a proc", :broken => true do
+ it "cleanup when passed a proc", gc_dependent: true do
# NOTE: passing a proc is touchy, because it's so easy to create a memory leak.
#
# specifically, if we made an inline call to
@@ -317,7 +319,7 @@ describe "AutoPointer" do
end
# see #427
- it "cleanup when passed a method", :broken => true do
+ it "cleanup when passed a method", gc_dependent: true do
expect(AutoPointerTestHelper).to receive(:release).at_least(loop_count-wiggle_room).times
AutoPointerTestHelper.reset
loop_count.times do
@@ -334,6 +336,7 @@ describe "AutoPointer" do
ffi_lib TestLibrary::PATH
class CustomAutoPointer < FFI::AutoPointer
def self.release(ptr); end
+ private_class_method(:release)
end
attach_function :ptr_from_address, [ FFI::Platform::ADDRESS_SIZE == 32 ? :uint : :ulong_long ], CustomAutoPointer
end
@@ -356,6 +359,7 @@ describe "AutoPointer" do
describe "#autorelease?" do
ptr_class = Class.new(FFI::AutoPointer) do
def self.release(ptr); end
+ private_class_method(:release)
end
it "should be true by default" do
@@ -377,6 +381,7 @@ describe "AutoPointer" do
describe "#type_size" do
ptr_class = Class.new(FFI::AutoPointer) do
def self.release(ptr); end
+ private_class_method(:release)
end
it "type_size of AutoPointer should match wrapped Pointer" do
diff --git a/spec/ffi/spec_helper.rb b/spec/ffi/spec_helper.rb
index 3d8a025..22d1c47 100644
--- a/spec/ffi/spec_helper.rb
+++ b/spec/ffi/spec_helper.rb
@@ -8,7 +8,7 @@ require 'timeout'
require 'objspace'
RSpec.configure do |c|
- c.filter_run_excluding :broken => true
+ c.filter_run_excluding gc_dependent: true unless ENV['FFI_TEST_GC'] == 'true'
c.filter_run_excluding( :ractor ) unless defined?(Ractor) && RUBY_VERSION >= "3.1"
end