diff --git a/bench/bench_FFFrV.rb b/bench/bench_FFFrV.rb index 89fe79a67..81207f7e6 100644 --- a/bench/bench_FFFrV.rb +++ b/bench/bench_FFFrV.rb @@ -1,24 +1,26 @@ require_relative 'bench_helper' -module LibTest - extend FFI::Library - ffi_lib LIBTEST_PATH - attach_function :bench_f32f32f32_v, [ :float, :float, :float ], :void - def self.rb_bench(a0, a1, a2); nil; end -end +module BenchFFFrV + module LibTest + extend FFI::Library + ffi_lib LIBTEST_PATH + attach_function :bench_f32f32f32_v, [ :float, :float, :float ], :void + def self.rb_bench(a0, a1, a2); nil; end + end -puts "Benchmark [ :float, :float, :float ], :void performance, #{ITER}x calls" -f = 1.0 -10.times { - puts Benchmark.measure { - ITER.times { LibTest.bench_f32f32f32_v(f, f, f) } + puts "Benchmark [ :float, :float, :float ], :void performance, #{ITER}x calls" + f = 1.0 + 10.times { + puts Benchmark.measure { + ITER.times { LibTest.bench_f32f32f32_v(f, f, f) } + } } -} -puts "Benchmark ruby method(1 arg) performance, #{ITER}x calls" -10.times { - puts Benchmark.measure { - ITER.times { LibTest.rb_bench(f, f, f) } + puts "Benchmark ruby method(1 arg) performance, #{ITER}x calls" + 10.times { + puts Benchmark.measure { + ITER.times { LibTest.rb_bench(f, f, f) } + } } -} +end diff --git a/bench/bench_FrV.rb b/bench/bench_FrV.rb index d1aa3d7cf..cc2e7917f 100644 --- a/bench/bench_FrV.rb +++ b/bench/bench_FrV.rb @@ -1,36 +1,38 @@ require_relative 'bench_helper' -module LibTest - extend FFI::Library - ffi_lib LIBTEST_PATH - attach_function :bench_f32_v, [ :float ], :void - def self.rb_bench(i0); nil; end -end +module BenchFrV + module LibTest + extend FFI::Library + ffi_lib LIBTEST_PATH + attach_function :bench_f32_v, [ :float ], :void + def self.rb_bench(i0); nil; end + end -puts "Benchmark [ :float ], :void performance, #{ITER}x calls" -f = 1.0 -10.times { - puts Benchmark.measure { - i = 0; while i < ITER - LibTest.bench_f32_v(f) - LibTest.bench_f32_v(f) - LibTest.bench_f32_v(f) - LibTest.bench_f32_v(f) - i += 4 - end + puts "Benchmark [ :float ], :void performance, #{ITER}x calls" + f = 1.0 + 10.times { + puts Benchmark.measure { + i = 0; while i < ITER + LibTest.bench_f32_v(f) + LibTest.bench_f32_v(f) + LibTest.bench_f32_v(f) + LibTest.bench_f32_v(f) + i += 4 + end + } } -} -puts "Benchmark ruby method(1 arg) performance, #{ITER}x calls" -10.times { - puts Benchmark.measure { - i = 0; while i < ITER - LibTest.rb_bench(f) - LibTest.rb_bench(f) - LibTest.rb_bench(f) - LibTest.rb_bench(f) - i += 4 - end + puts "Benchmark ruby method(1 arg) performance, #{ITER}x calls" + 10.times { + puts Benchmark.measure { + i = 0; while i < ITER + LibTest.rb_bench(f) + LibTest.rb_bench(f) + LibTest.rb_bench(f) + LibTest.rb_bench(f) + i += 4 + end + } } -} +end diff --git a/bench/bench_IIIIIIrV.rb b/bench/bench_IIIIIIrV.rb index 3849204af..671be9dd9 100644 --- a/bench/bench_IIIIIIrV.rb +++ b/bench/bench_IIIIIIrV.rb @@ -1,29 +1,30 @@ require_relative 'bench_helper' -module LibTest - extend FFI::Library - ffi_lib LIBTEST_PATH - attach_function :ffi_bench, 'bench_s32s32s32s32s32s32_v', [ :int, :int, :int, :int, :int, :int ], :void, :save_errno => false - def self.rb_bench(i0, i1, i2, i3, i4, i5); nil; end -end +module BenchIIIIIIrV + module LibTest + extend FFI::Library + ffi_lib LIBTEST_PATH + attach_function :ffi_bench, 'bench_s32s32s32s32s32s32_v', [ :int, :int, :int, :int, :int, :int ], :void, :save_errno => false + def self.rb_bench(i0, i1, i2, i3, i4, i5); nil; end + end -puts "Benchmark [ :int, :int, :int, :int, :int, :int ], :void performance, #{ITER}x calls" -10.times { - puts Benchmark.measure { - i = 0; while i < ITER - LibTest.ffi_bench(1, 2, 3, 4, 5, 6) - i += 1 - end + puts "Benchmark [ :int, :int, :int, :int, :int, :int ], :void performance, #{ITER}x calls" + 10.times { + puts Benchmark.measure { + i = 0; while i < ITER + LibTest.ffi_bench(1, 2, 3, 4, 5, 6) + i += 1 + end + } } -} -puts "Benchmark ruby method(6 arg) performance, #{ITER}x calls" -10.times { - puts Benchmark.measure { - i = 0; while i < ITER - LibTest.rb_bench(0, 1, 2, 3, 4, 5) - i += 1 - end + puts "Benchmark ruby method(6 arg) performance, #{ITER}x calls" + 10.times { + puts Benchmark.measure { + i = 0; while i < ITER + LibTest.rb_bench(0, 1, 2, 3, 4, 5) + i += 1 + end + } } -} - +end diff --git a/bench/bench_IIIrI.rb b/bench/bench_IIIrI.rb index cf8e4dedf..0bb30efc4 100644 --- a/bench/bench_IIIrI.rb +++ b/bench/bench_IIIrI.rb @@ -1,15 +1,17 @@ require_relative 'bench_helper' -module LibTest - extend FFI::Library - ffi_lib LIBTEST_PATH - attach_function :bench, :bench_s32s32s32_v, [ :int, :int, :int ], :int -end +module BenchIIIrI + module LibTest + extend FFI::Library + ffi_lib LIBTEST_PATH + attach_function :bench, :bench_s32s32s32_v, [ :int, :int, :int ], :int + end -puts "Benchmark [ :int, :int, :int ], :int performance, #{ITER}x calls" -10.times { - puts Benchmark.measure { - ITER.times { LibTest.bench(0, 1, 2) } + puts "Benchmark [ :int, :int, :int ], :int performance, #{ITER}x calls" + 10.times { + puts Benchmark.measure { + ITER.times { LibTest.bench(0, 1, 2) } + } } -} +end diff --git a/bench/bench_IIIrV.rb b/bench/bench_IIIrV.rb index 1dfa5a09d..f1a8bef76 100644 --- a/bench/bench_IIIrV.rb +++ b/bench/bench_IIIrV.rb @@ -1,28 +1,30 @@ require_relative 'bench_helper' -module LibTest - extend FFI::Library - ffi_lib LIBTEST_PATH - attach_function :ffi_bench, :bench_s32s32s32_v, [ :int, :int, :int ], :void, :save_errno => false - def self.rb_bench(i0, i1, i2); nil; end -end +module BenchIIIrV + module LibTest + extend FFI::Library + ffi_lib LIBTEST_PATH + attach_function :ffi_bench, :bench_s32s32s32_v, [ :int, :int, :int ], :void, :save_errno => false + def self.rb_bench(i0, i1, i2); nil; end + end -puts "Benchmark [ :int, :int, :int ], :void performance, #{ITER}x calls" -10.times { - puts Benchmark.measure { - i = 0; while i < ITER - LibTest.ffi_bench(0, 1, 2) - i += 1 - end + puts "Benchmark [ :int, :int, :int ], :void performance, #{ITER}x calls" + 10.times { + puts Benchmark.measure { + i = 0; while i < ITER + LibTest.ffi_bench(0, 1, 2) + i += 1 + end + } } -} -puts "Benchmark ruby method(3 arg) performance, #{ITER}x calls" -10.times { - puts Benchmark.measure { - i = 0; while i < ITER - LibTest.rb_bench(0, 1, 2) - i += 1 - end + puts "Benchmark ruby method(3 arg) performance, #{ITER}x calls" + 10.times { + puts Benchmark.measure { + i = 0; while i < ITER + LibTest.rb_bench(0, 1, 2) + i += 1 + end + } } -} +end diff --git a/bench/bench_IrV.rb b/bench/bench_IrV.rb index 0a9447da4..1bd2a27c2 100644 --- a/bench/bench_IrV.rb +++ b/bench/bench_IrV.rb @@ -1,34 +1,36 @@ require_relative 'bench_helper' -module LibTest - extend FFI::Library - ffi_lib LIBTEST_PATH - attach_function :ffi_bench, :bench_s32_v, [ :int ], :void, :save_errno => false - def self.rb_bench(i0); nil; end -end +module BenchIrV + module LibTest + extend FFI::Library + ffi_lib LIBTEST_PATH + attach_function :ffi_bench, :bench_s32_v, [ :int ], :void, :save_errno => false + def self.rb_bench(i0); nil; end + end -puts "Benchmark [ :int ], :void performance, #{ITER}x calls" -10.times { - puts Benchmark.measure { - i = 0; while i < ITER - LibTest.ffi_bench(0) - LibTest.ffi_bench(0) - LibTest.ffi_bench(0) - LibTest.ffi_bench(0) - i += 4 - end + puts "Benchmark [ :int ], :void performance, #{ITER}x calls" + 10.times { + puts Benchmark.measure { + i = 0; while i < ITER + LibTest.ffi_bench(0) + LibTest.ffi_bench(0) + LibTest.ffi_bench(0) + LibTest.ffi_bench(0) + i += 4 + end + } } -} -puts "Benchmark ruby method(1 arg) performance, #{ITER}x calls" -10.times { - puts Benchmark.measure { - i = 0; while i < ITER - LibTest.rb_bench(0) - LibTest.rb_bench(0) - LibTest.rb_bench(0) - LibTest.rb_bench(0) - i += 4 - end + puts "Benchmark ruby method(1 arg) performance, #{ITER}x calls" + 10.times { + puts Benchmark.measure { + i = 0; while i < ITER + LibTest.rb_bench(0) + LibTest.rb_bench(0) + LibTest.rb_bench(0) + LibTest.rb_bench(0) + i += 4 + end + } } -} +end diff --git a/bench/bench_LLLrV.rb b/bench/bench_LLLrV.rb index 067fe06bf..b633483cd 100644 --- a/bench/bench_LLLrV.rb +++ b/bench/bench_LLLrV.rb @@ -1,20 +1,21 @@ require_relative 'bench_helper' -module LibTest - extend FFI::Library - ffi_lib LIBTEST_PATH - attach_function :bench_s64s64s64_v, [ :long_long, :long_long, :long_long ], :void, :save_errno => false -end +module BenchLLLrV + module LibTest + extend FFI::Library + ffi_lib LIBTEST_PATH + attach_function :bench_s64s64s64_v, [ :long_long, :long_long, :long_long ], :void, :save_errno => false + end -puts "Benchmark [ :long_long, :long_long, :long_long ], :void performance, #{ITER}x calls" + puts "Benchmark [ :long_long, :long_long, :long_long ], :void performance, #{ITER}x calls" -10.times { - puts Benchmark.measure { - i = 0; while i < ITER - LibTest.bench_s64s64s64_v(0, 1, 2) - i += 1 - end + 10.times { + puts Benchmark.measure { + i = 0; while i < ITER + LibTest.bench_s64s64s64_v(0, 1, 2) + i += 1 + end + } } -} - +end diff --git a/bench/bench_PPPrV.rb b/bench/bench_PPPrV.rb index 6764ea1fe..edd7ff47f 100644 --- a/bench/bench_PPPrV.rb +++ b/bench/bench_PPPrV.rb @@ -1,112 +1,114 @@ require_relative 'bench_helper' -module LibTest - extend FFI::Library - ffi_lib LIBTEST_PATH +module BenchPPPrV + module LibTest + extend FFI::Library + ffi_lib LIBTEST_PATH - attach_function :bench_ptr, :bench_PPP_v, [ :pointer, :pointer, :pointer ], :void, :save_errno => false - attach_function :bench_buffer, :bench_PPP_v, [ :pointer, :pointer, :pointer ], :void, :save_errno => false - attach_function :bench_struct, :bench_PPP_v, [ :pointer, :pointer, :pointer ], :void, :save_errno => false - attach_function :bench_nil, :bench_PPP_v, [ :pointer, :pointer, :pointer ], :void, :save_errno => false - attach_function :bench_conv, :bench_PPP_v, [ :pointer, :pointer, :pointer ], :void, :save_errno => false -end + attach_function :bench_ptr, :bench_PPP_v, [ :pointer, :pointer, :pointer ], :void, :save_errno => false + attach_function :bench_buffer, :bench_PPP_v, [ :pointer, :pointer, :pointer ], :void, :save_errno => false + attach_function :bench_struct, :bench_PPP_v, [ :pointer, :pointer, :pointer ], :void, :save_errno => false + attach_function :bench_nil, :bench_PPP_v, [ :pointer, :pointer, :pointer ], :void, :save_errno => false + attach_function :bench_conv, :bench_PPP_v, [ :pointer, :pointer, :pointer ], :void, :save_errno => false + end -puts "Benchmark [ :pointer, :pointer, :pointer ], :void performance, #{ITER}x calls" -ptr = FFI::MemoryPointer.new :int -10.times { - puts Benchmark.measure { - i = 0; while i < ITER - LibTest.bench_ptr(ptr, ptr, ptr) - LibTest.bench_ptr(ptr, ptr, ptr) - LibTest.bench_ptr(ptr, ptr, ptr) - LibTest.bench_ptr(ptr, ptr, ptr) - i += 4 - end + puts "Benchmark [ :pointer, :pointer, :pointer ], :void performance, #{ITER}x calls" + ptr = FFI::MemoryPointer.new :int + 10.times { + puts Benchmark.measure { + i = 0; while i < ITER + LibTest.bench_ptr(ptr, ptr, ptr) + LibTest.bench_ptr(ptr, ptr, ptr) + LibTest.bench_ptr(ptr, ptr, ptr) + LibTest.bench_ptr(ptr, ptr, ptr) + i += 4 + end + } } -} -puts "Benchmark [ :pointer, :pointer, :pointer ], :void with Struct parameters performance #{ITER}x calls" + puts "Benchmark [ :pointer, :pointer, :pointer ], :void with Struct parameters performance #{ITER}x calls" -class TestStruct < FFI::Struct - layout :i, :int -end + class TestStruct < FFI::Struct + layout :i, :int + end -s = TestStruct.new(FFI::MemoryPointer.new(TestStruct)); -10.times { - puts Benchmark.measure { - i = 0; while i < ITER - LibTest.bench_struct(s, s, s) - LibTest.bench_struct(s, s, s) - LibTest.bench_struct(s, s, s) - LibTest.bench_struct(s, s, s) - i += 4 - end + s = TestStruct.new(FFI::MemoryPointer.new(TestStruct)); + 10.times { + puts Benchmark.measure { + i = 0; while i < ITER + LibTest.bench_struct(s, s, s) + LibTest.bench_struct(s, s, s) + LibTest.bench_struct(s, s, s) + LibTest.bench_struct(s, s, s) + i += 4 + end + } } -} -puts "Benchmark [ :pointer, :pointer, :pointer ], :void with Buffer parameters performance, #{ITER}x calls" -ptr = FFI::Buffer.new(:int) -10.times { - puts Benchmark.measure { - i = 0; while i < ITER - LibTest.bench_buffer(ptr, ptr, ptr) - LibTest.bench_buffer(ptr, ptr, ptr) - LibTest.bench_buffer(ptr, ptr, ptr) - LibTest.bench_buffer(ptr, ptr, ptr) - i += 4 - end + puts "Benchmark [ :pointer, :pointer, :pointer ], :void with Buffer parameters performance, #{ITER}x calls" + ptr = FFI::Buffer.new(:int) + 10.times { + puts Benchmark.measure { + i = 0; while i < ITER + LibTest.bench_buffer(ptr, ptr, ptr) + LibTest.bench_buffer(ptr, ptr, ptr) + LibTest.bench_buffer(ptr, ptr, ptr) + LibTest.bench_buffer(ptr, ptr, ptr) + i += 4 + end + } } -} -puts "Benchmark [ :pointer, :pointer, :pointer ], :void with nil parameters performance, #{ITER}x calls" -10.times { - puts Benchmark.measure { - i = 0; while i < ITER - LibTest.bench_nil(nil, nil, nil) - LibTest.bench_nil(nil, nil, nil) - LibTest.bench_nil(nil, nil, nil) - LibTest.bench_nil(nil, nil, nil) - i += 4 - end + puts "Benchmark [ :pointer, :pointer, :pointer ], :void with nil parameters performance, #{ITER}x calls" + 10.times { + puts Benchmark.measure { + i = 0; while i < ITER + LibTest.bench_nil(nil, nil, nil) + LibTest.bench_nil(nil, nil, nil) + LibTest.bench_nil(nil, nil, nil) + LibTest.bench_nil(nil, nil, nil) + i += 4 + end + } } -} -puts "Benchmark [ :pointer, :pointer, :pointer ], :void with string parameters performance, #{ITER}x calls" -ptr = 0.chr * 4 -10.times { - puts Benchmark.measure { - i = 0; while i < ITER - LibTest.bench_ptr(ptr, ptr, ptr) - LibTest.bench_ptr(ptr, ptr, ptr) - LibTest.bench_ptr(ptr, ptr, ptr) - LibTest.bench_ptr(ptr, ptr, ptr) - i += 4 - end + puts "Benchmark [ :pointer, :pointer, :pointer ], :void with string parameters performance, #{ITER}x calls" + ptr = 0.chr * 4 + 10.times { + puts Benchmark.measure { + i = 0; while i < ITER + LibTest.bench_ptr(ptr, ptr, ptr) + LibTest.bench_ptr(ptr, ptr, ptr) + LibTest.bench_ptr(ptr, ptr, ptr) + LibTest.bench_ptr(ptr, ptr, ptr) + i += 4 + end + } } -} -class PointerType - def initialize(ptr) - @pointer = ptr - end + class PointerType + def initialize(ptr) + @pointer = ptr + end - def to_ptr - @pointer + def to_ptr + @pointer + end end -end -puts "Benchmark [ :pointer, :pointer, :pointer ], :void with to_ptr converting parameters performance, #{ITER}x calls" -ptr = PointerType.new(FFI::MemoryPointer.new(:int)) -10.times { - puts Benchmark.measure { - i = 0; while i < ITER - LibTest.bench_conv(ptr, ptr, ptr) - LibTest.bench_conv(ptr, ptr, ptr) - LibTest.bench_conv(ptr, ptr, ptr) - LibTest.bench_conv(ptr, ptr, ptr) - i += 4 - end + puts "Benchmark [ :pointer, :pointer, :pointer ], :void with to_ptr converting parameters performance, #{ITER}x calls" + ptr = PointerType.new(FFI::MemoryPointer.new(:int)) + 10.times { + puts Benchmark.measure { + i = 0; while i < ITER + LibTest.bench_conv(ptr, ptr, ptr) + LibTest.bench_conv(ptr, ptr, ptr) + LibTest.bench_conv(ptr, ptr, ptr) + LibTest.bench_conv(ptr, ptr, ptr) + i += 4 + end + } } -} +end diff --git a/bench/bench_PPrV.rb b/bench/bench_PPrV.rb index f4e5afb7e..6842110e1 100644 --- a/bench/bench_PPrV.rb +++ b/bench/bench_PPrV.rb @@ -1,69 +1,69 @@ require_relative 'bench_helper' -module LibTest - extend FFI::Library - ffi_lib LIBTEST_PATH +module BenchPPrV + module LibTest + extend FFI::Library + ffi_lib LIBTEST_PATH - attach_function :bench, :bench_PP_v, [ :buffer_in, :buffer_in ], :void -end + attach_function :bench, :bench_PP_v, [ :buffer_in, :buffer_in ], :void + end -puts "Benchmark [ :buffer_in, :pointer ], :void performance, #{ITER}x calls" -ptr = FFI::MemoryPointer.new :int -10.times { - puts Benchmark.measure { - ITER.times { LibTest.bench(ptr, ptr) } + puts "Benchmark [ :buffer_in, :pointer ], :void performance, #{ITER}x calls" + ptr = FFI::MemoryPointer.new :int + 10.times { + puts Benchmark.measure { + ITER.times { LibTest.bench(ptr, ptr) } + } } -} -puts "Benchmark [ :buffer_in, :buffer_in ], :void with Struct parameters performance #{ITER}x calls" + puts "Benchmark [ :buffer_in, :buffer_in ], :void with Struct parameters performance #{ITER}x calls" -class TestStruct < FFI::Struct - layout :i, :int -end + class TestStruct < FFI::Struct + layout :i, :int + end -s = TestStruct.new(FFI::MemoryPointer.new(TestStruct)); -10.times { - puts Benchmark.measure { - ITER.times { LibTest.bench(s, s) } + s = TestStruct.new(FFI::MemoryPointer.new(TestStruct)); + 10.times { + puts Benchmark.measure { + ITER.times { LibTest.bench(s, s) } + } } -} -puts "Benchmark [ :buffer_in, :buffer_in ], :void with nil parameters performance, #{ITER}x calls" -10.times { - puts Benchmark.measure { - ITER.times { LibTest.bench(nil, nil) } + puts "Benchmark [ :buffer_in, :buffer_in ], :void with nil parameters performance, #{ITER}x calls" + 10.times { + puts Benchmark.measure { + ITER.times { LibTest.bench(nil, nil) } + } } -} -puts "Benchmark [ :buffer_in, :buffer_in ], :void with Buffer parameters performance, #{ITER}x calls" -ptr = FFI::Buffer.new(:int) -10.times { - puts Benchmark.measure { - ITER.times { LibTest.bench(ptr, ptr) } + puts "Benchmark [ :buffer_in, :buffer_in ], :void with Buffer parameters performance, #{ITER}x calls" + ptr = FFI::Buffer.new(:int) + 10.times { + puts Benchmark.measure { + ITER.times { LibTest.bench(ptr, ptr) } + } } -} -puts "Benchmark [ :buffer_in, :buffer_in ], :void with one nil, one Buffer parameter performance, #{ITER}x calls" -ptr = FFI::Buffer.new(:int) -10.times { - puts Benchmark.measure { - ITER.times { LibTest.bench(nil, ptr) } + puts "Benchmark [ :buffer_in, :buffer_in ], :void with one nil, one Buffer parameter performance, #{ITER}x calls" + ptr = FFI::Buffer.new(:int) + 10.times { + puts Benchmark.measure { + ITER.times { LibTest.bench(nil, ptr) } + } } -} -puts "Benchmark [ :buffer_in, :buffer_in ], :void with loop-allocated Buffer parameters performance, #{ITER}x calls" -10.times { - puts Benchmark.measure { - ITER.times { LibTest.bench(FFI::Buffer.new(:int), FFI::Buffer.new(:int)) } + puts "Benchmark [ :buffer_in, :buffer_in ], :void with loop-allocated Buffer parameters performance, #{ITER}x calls" + 10.times { + puts Benchmark.measure { + ITER.times { LibTest.bench(FFI::Buffer.new(:int), FFI::Buffer.new(:int)) } + } } -} -puts "Benchmark [ :buffer_in, :buffer_in ], :void with loop-allocated MemoryPointer parameters performance, #{ITER}x calls" -10.times { - puts Benchmark.measure { - ITER.times { LibTest.bench(FFI::MemoryPointer.new(:int), FFI::MemoryPointer.new(:int)) } + puts "Benchmark [ :buffer_in, :buffer_in ], :void with loop-allocated MemoryPointer parameters performance, #{ITER}x calls" + 10.times { + puts Benchmark.measure { + ITER.times { LibTest.bench(FFI::MemoryPointer.new(:int), FFI::MemoryPointer.new(:int)) } + } } -} - - +end diff --git a/bench/bench_PrV.rb b/bench/bench_PrV.rb index 7e3f401ad..baf1935e7 100644 --- a/bench/bench_PrV.rb +++ b/bench/bench_PrV.rb @@ -1,101 +1,101 @@ require_relative 'bench_helper' -module LibTest - extend FFI::Library - ffi_lib LIBTEST_PATH +module BenchPrV + module LibTest + extend FFI::Library + ffi_lib LIBTEST_PATH - attach_function :bench, :bench_P_v, [ :buffer_in ], :void, :save_errno => false -end + attach_function :bench, :bench_P_v, [ :buffer_in ], :void, :save_errno => false + end -puts "Benchmark [ :buffer_in ], :void performance (pre allocated pointer), #{ITER}x calls" -ptr = FFI::MemoryPointer.new :int -10.times { - puts Benchmark.measure { - i = 0; while i < ITER - LibTest.bench(ptr) - LibTest.bench(ptr) - LibTest.bench(ptr) - LibTest.bench(ptr) - i += 4 - end + puts "Benchmark [ :buffer_in ], :void performance (pre allocated pointer), #{ITER}x calls" + ptr = FFI::MemoryPointer.new :int + 10.times { + puts Benchmark.measure { + i = 0; while i < ITER + LibTest.bench(ptr) + LibTest.bench(ptr) + LibTest.bench(ptr) + LibTest.bench(ptr) + i += 4 + end + } } -} -puts "Benchmark [ :buffer_in ], :void performance (nil param), #{ITER}x calls" -10.times { - puts Benchmark.measure { - i = 0; while i < ITER - LibTest.bench(nil) - LibTest.bench(nil) - LibTest.bench(nil) - LibTest.bench(nil) - i += 4 - end + puts "Benchmark [ :buffer_in ], :void performance (nil param), #{ITER}x calls" + 10.times { + puts Benchmark.measure { + i = 0; while i < ITER + LibTest.bench(nil) + LibTest.bench(nil) + LibTest.bench(nil) + LibTest.bench(nil) + i += 4 + end + } } -} -puts "Benchmark [ :buffer_in ], :void performance (pre allocated Buffer param), #{ITER}x calls" -ptr = FFI::Buffer.new :int -10.times { - puts Benchmark.measure { - i = 0; while i < ITER - LibTest.bench(ptr) - LibTest.bench(ptr) - LibTest.bench(ptr) - LibTest.bench(ptr) - i += 4 - end + puts "Benchmark [ :buffer_in ], :void performance (pre allocated Buffer param), #{ITER}x calls" + ptr = FFI::Buffer.new :int + 10.times { + puts Benchmark.measure { + i = 0; while i < ITER + LibTest.bench(ptr) + LibTest.bench(ptr) + LibTest.bench(ptr) + LibTest.bench(ptr) + i += 4 + end + } } -} -puts "Benchmark [ :buffer_in ], :void performance (const String param), #{ITER}x calls" -ptr = 'test' -10.times { - puts Benchmark.measure { - i = 0; while i < ITER - LibTest.bench(ptr) - LibTest.bench(ptr) - LibTest.bench(ptr) - LibTest.bench(ptr) - i += 4 - end + puts "Benchmark [ :buffer_in ], :void performance (const String param), #{ITER}x calls" + ptr = 'test' + 10.times { + puts Benchmark.measure { + i = 0; while i < ITER + LibTest.bench(ptr) + LibTest.bench(ptr) + LibTest.bench(ptr) + LibTest.bench(ptr) + i += 4 + end + } } -} -puts "Benchmark [ :buffer_in ], :void performance (loop-allocated Buffer param), #{ITER}x calls" -10.times { - puts Benchmark.measure { - i = 0; while i < ITER - LibTest.bench(FFI::Buffer.new(4)) - LibTest.bench(FFI::Buffer.new(4)) - LibTest.bench(FFI::Buffer.new(4)) - LibTest.bench(FFI::Buffer.new(4)) - i += 4 - end + puts "Benchmark [ :buffer_in ], :void performance (loop-allocated Buffer param), #{ITER}x calls" + 10.times { + puts Benchmark.measure { + i = 0; while i < ITER + LibTest.bench(FFI::Buffer.new(4)) + LibTest.bench(FFI::Buffer.new(4)) + LibTest.bench(FFI::Buffer.new(4)) + LibTest.bench(FFI::Buffer.new(4)) + i += 4 + end + } } -} -puts "Benchmark [ :buffer_in ], :void performance (loop-allocated String param), #{ITER}x calls" -10.times { - puts Benchmark.measure { - i = 0; while i < ITER - LibTest.bench(String.new) - LibTest.bench(String.new) - LibTest.bench(String.new) - LibTest.bench(String.new) - i += 4 - end + puts "Benchmark [ :buffer_in ], :void performance (loop-allocated String param), #{ITER}x calls" + 10.times { + puts Benchmark.measure { + i = 0; while i < ITER + LibTest.bench(String.new) + LibTest.bench(String.new) + LibTest.bench(String.new) + LibTest.bench(String.new) + i += 4 + end + } } -} -puts "Benchmark [ :buffer_in ], :void performance (loop-allocated MemoryPointer param), #{ITER}x calls" -10.times { - puts Benchmark.measure { - i = 0; while i < ITER - LibTest.bench(FFI::MemoryPointer.new(4)) - LibTest.bench(FFI::MemoryPointer.new(4)) - LibTest.bench(FFI::MemoryPointer.new(4)) - LibTest.bench(FFI::MemoryPointer.new(4)) - i += 4 - end + puts "Benchmark [ :buffer_in ], :void performance (loop-allocated MemoryPointer param), #{ITER}x calls" + 10.times { + puts Benchmark.measure { + i = 0; while i < ITER + LibTest.bench(FFI::MemoryPointer.new(4)) + LibTest.bench(FFI::MemoryPointer.new(4)) + LibTest.bench(FFI::MemoryPointer.new(4)) + LibTest.bench(FFI::MemoryPointer.new(4)) + i += 4 + end + } } -} - - +end diff --git a/bench/bench_SrV.rb b/bench/bench_SrV.rb index 04128d540..49c41082f 100644 --- a/bench/bench_SrV.rb +++ b/bench/bench_SrV.rb @@ -1,16 +1,18 @@ require_relative 'bench_helper' -module LibTest - extend FFI::Library - ffi_lib LIBTEST_PATH - attach_function :bench_S_v, [ :string ], :void -end +module BenchSrV + module LibTest + extend FFI::Library + ffi_lib LIBTEST_PATH + attach_function :bench_S_v, [ :string ], :void + end -puts "Benchmark [ :string ], :void performance, #{ITER}x calls" + puts "Benchmark [ :string ], :void performance, #{ITER}x calls" -s = 'a' * 1000 -10.times { - puts Benchmark.measure { - ITER.times { LibTest.bench_S_v(s) } + s = 'a' * 1000 + 10.times { + puts Benchmark.measure { + ITER.times { LibTest.bench_S_v(s) } + } } -} +end diff --git a/bench/bench_VrI.rb b/bench/bench_VrI.rb index 82850e94b..8ee08bb52 100644 --- a/bench/bench_VrI.rb +++ b/bench/bench_VrI.rb @@ -1,36 +1,38 @@ require_relative 'bench_helper' -module LibTest - extend FFI::Library - ffi_lib LIBTEST_PATH - attach_function :ffi_bench, :returnInt, [ ], :int, :save_errno => false - def self.rb_bench; 0xdeadbeef; end -end +module BenchVrI + module LibTest + extend FFI::Library + ffi_lib LIBTEST_PATH + attach_function :ffi_bench, :returnInt, [ ], :int, :save_errno => false + def self.rb_bench; 0xdeadbeef; end + end -puts "Benchmark [ ], :int performance, #{ITER}x calls" -10.times { - puts Benchmark.measure { - i = 0; max = ITER / 4 - while i < max - LibTest.ffi_bench - LibTest.ffi_bench - LibTest.ffi_bench - LibTest.ffi_bench - i += 1 - end + puts "Benchmark [ ], :int performance, #{ITER}x calls" + 10.times { + puts Benchmark.measure { + i = 0; max = ITER / 4 + while i < max + LibTest.ffi_bench + LibTest.ffi_bench + LibTest.ffi_bench + LibTest.ffi_bench + i += 1 + end + } } -} -puts "Benchmark ruby method(), nil performance, #{ITER}x calls" -10.times { - puts Benchmark.measure { - i = 0; max = ITER / 4 - while i < max - LibTest.rb_bench - LibTest.rb_bench - LibTest.rb_bench - LibTest.rb_bench - i += 1 - end + puts "Benchmark ruby method(), nil performance, #{ITER}x calls" + 10.times { + puts Benchmark.measure { + i = 0; max = ITER / 4 + while i < max + LibTest.rb_bench + LibTest.rb_bench + LibTest.rb_bench + LibTest.rb_bench + i += 1 + end + } } -} +end diff --git a/bench/bench_VrV.rb b/bench/bench_VrV.rb index 7ef9c07a4..0210ae3ca 100644 --- a/bench/bench_VrV.rb +++ b/bench/bench_VrV.rb @@ -1,43 +1,44 @@ require_relative 'bench_helper' -module LibTest - extend FFI::Library - ffi_lib LIBTEST_PATH - attach_function :ffi_bench, :returnVoid, [ ], :void - attach_function :ffi_bench_noerrno, :returnVoid, [ ], :void, :save_errno => false - def self.rb_bench; nil; end -end +module BenchVrV + module LibTest + extend FFI::Library + ffi_lib LIBTEST_PATH + attach_function :ffi_bench, :returnVoid, [ ], :void + attach_function :ffi_bench_noerrno, :returnVoid, [ ], :void, :save_errno => false + def self.rb_bench; nil; end + end -puts "Benchmark [ ], :void performance, #{ITER}x calls" -10.times { - puts Benchmark.measure { - i = 0 - while i < ITER - LibTest.ffi_bench - i += 1 - end + puts "Benchmark [ ], :void performance, #{ITER}x calls" + 10.times { + puts Benchmark.measure { + i = 0 + while i < ITER + LibTest.ffi_bench + i += 1 + end + } } -} -puts "Benchmark [ ], :void no-errno performance, #{ITER}x calls" -10.times { - puts Benchmark.measure { - i = 0 - while i < ITER - LibTest.ffi_bench_noerrno - i += 1 - end + puts "Benchmark [ ], :void no-errno performance, #{ITER}x calls" + 10.times { + puts Benchmark.measure { + i = 0 + while i < ITER + LibTest.ffi_bench_noerrno + i += 1 + end + } } -} -puts "Benchmark ruby method(no arg) performance, #{ITER}x calls" -10.times { - puts Benchmark.measure { - i = 0 - while i < ITER - LibTest.rb_bench - i += 1 - end + puts "Benchmark ruby method(no arg) performance, #{ITER}x calls" + 10.times { + puts Benchmark.measure { + i = 0 + while i < ITER + LibTest.rb_bench + i += 1 + end + } } -} - +end diff --git a/bench/bench_autoptr.rb b/bench/bench_autoptr.rb index 3c8a635b0..f8946d105 100644 --- a/bench/bench_autoptr.rb +++ b/bench/bench_autoptr.rb @@ -1,39 +1,41 @@ require_relative 'bench_helper' -iter = ITER +module BenchAutoptr + iter = ITER -class Ptr < FFI::AutoPointer - def self.release(ptr) - LibC.free(ptr); + class Ptr < FFI::AutoPointer + def self.release(ptr) + LibC.free(ptr); + end end -end -module LibC - extend FFI::Library - ffi_lib FFI::Library::LIBC - attach_function :malloc, [ :long ], Ptr, :ignore_error => true - attach_function :malloc2, :malloc, [ :long ], :pointer, :ignore_error => true - attach_function :free, [ :pointer ], :void, :ignore_error => true - def self.finalizer(ptr) - proc { LibC.free(ptr) } + module LibC + extend FFI::Library + ffi_lib FFI::Library::LIBC + attach_function :malloc, [ :long ], Ptr, :ignore_error => true + attach_function :malloc2, :malloc, [ :long ], :pointer, :ignore_error => true + attach_function :free, [ :pointer ], :void, :ignore_error => true + def self.finalizer(ptr) + proc { LibC.free(ptr) } + end end -end -puts "Benchmark AutoPointer.new performance, #{iter}x" -10.times { - puts Benchmark.measure { - iter.times { LibC.malloc(4) } + puts "Benchmark AutoPointer.new performance, #{iter}x" + 10.times { + puts Benchmark.measure { + iter.times { LibC.malloc(4) } + } } -} -puts "Benchmark ObjectSpace finalizer performance, #{iter}x" -10.times { - puts Benchmark.measure { - iter.times { - ptr = LibC.malloc2(4) - ptr2 = FFI::Pointer.new(ptr) - ObjectSpace.define_finalizer(ptr2, LibC.finalizer(ptr)) + puts "Benchmark ObjectSpace finalizer performance, #{iter}x" + 10.times { + puts Benchmark.measure { + iter.times { + ptr = LibC.malloc2(4) + ptr2 = FFI::Pointer.new(ptr) + ObjectSpace.define_finalizer(ptr2, LibC.finalizer(ptr)) + } } } -} +end diff --git a/bench/bench_buffer.rb b/bench/bench_buffer.rb index 8f030ce61..4c2322d65 100644 --- a/bench/bench_buffer.rb +++ b/bench/bench_buffer.rb @@ -1,109 +1,111 @@ require_relative 'bench_helper' -iter = ITER +module BenchBuffer + iter = ITER -module BufferBench - extend FFI::Library - extend FFI::Library - ffi_lib LIBTEST_PATH - attach_function :bench_s32_v, [ :int ], :void - begin - attach_function :bench_buffer_in, :ptr_ret_int32_t, [ :buffer_in, :int ], :void - rescue FFI::NotFoundError - # NetBSD uses #define instead of typedef for these - attach_function :bench_buffer_in, :ptr_ret___int32_t, [ :buffer_in, :int ], :void + module BufferBench + extend FFI::Library + extend FFI::Library + ffi_lib LIBTEST_PATH + attach_function :bench_s32_v, [ :int ], :void + begin + attach_function :bench_buffer_in, :ptr_ret_int32_t, [ :buffer_in, :int ], :void + rescue FFI::NotFoundError + # NetBSD uses #define instead of typedef for these + attach_function :bench_buffer_in, :ptr_ret___int32_t, [ :buffer_in, :int ], :void + end + begin + attach_function :bench_buffer_inout, :ptr_ret_int32_t, [ :buffer_inout, :int ], :void + rescue FFI::NotFoundError + # NetBSD uses #define instead of typedef for these + attach_function :bench_buffer_inout, :ptr_ret___int32_t, [ :buffer_inout, :int ], :void + end + begin + attach_function :bench_buffer_out, :ptr_ret_int32_t, [ :buffer_out, :int ], :void + rescue FFI::NotFoundError + # NetBSD uses #define instead of typedef for these + attach_function :bench_buffer_out, :ptr_ret___int32_t, [ :buffer_out, :int ], :void + end end - begin - attach_function :bench_buffer_inout, :ptr_ret_int32_t, [ :buffer_inout, :int ], :void - rescue FFI::NotFoundError - # NetBSD uses #define instead of typedef for these - attach_function :bench_buffer_inout, :ptr_ret___int32_t, [ :buffer_inout, :int ], :void + class IntStruct < FFI::Struct + layout :i, :int end - begin - attach_function :bench_buffer_out, :ptr_ret_int32_t, [ :buffer_out, :int ], :void - rescue FFI::NotFoundError - # NetBSD uses #define instead of typedef for these - attach_function :bench_buffer_out, :ptr_ret___int32_t, [ :buffer_out, :int ], :void - end -end -class IntStruct < FFI::Struct - layout :i, :int -end -puts "Benchmark FFI call(MemoryPointer.new(:int, 1, true)) performance, #{iter}x" -10.times { - puts Benchmark.measure { - iter.times { BufferBench.bench_buffer_inout(FFI::MemoryPointer.new(:int, 1, true), 0) } + puts "Benchmark FFI call(MemoryPointer.new(:int, 1, true)) performance, #{iter}x" + 10.times { + puts Benchmark.measure { + iter.times { BufferBench.bench_buffer_inout(FFI::MemoryPointer.new(:int, 1, true), 0) } + } } -} -puts "Benchmark FFI call(MemoryPointer.new(4, 1, true)) performance, #{iter}x" -10.times { - puts Benchmark.measure { - iter.times { BufferBench.bench_buffer_inout(FFI::MemoryPointer.new(4, 1, true), 0) } + puts "Benchmark FFI call(MemoryPointer.new(4, 1, true)) performance, #{iter}x" + 10.times { + puts Benchmark.measure { + iter.times { BufferBench.bench_buffer_inout(FFI::MemoryPointer.new(4, 1, true), 0) } + } } -} -puts "Benchmark FFI call(MemoryPointer.new(IntStruct, 1, true)) performance, #{iter}x" -10.times { - puts Benchmark.measure { - iter.times { BufferBench.bench_buffer_inout(FFI::MemoryPointer.new(IntStruct, 1, true), 0) } + puts "Benchmark FFI call(MemoryPointer.new(IntStruct, 1, true)) performance, #{iter}x" + 10.times { + puts Benchmark.measure { + iter.times { BufferBench.bench_buffer_inout(FFI::MemoryPointer.new(IntStruct, 1, true), 0) } + } } -} -puts "Benchmark FFI call(0.chr * 4) performance, #{iter}x" -10.times { - puts Benchmark.measure { - iter.times { BufferBench.bench_buffer_inout(0.chr * 4, 0) } + puts "Benchmark FFI call(0.chr * 4) performance, #{iter}x" + 10.times { + puts Benchmark.measure { + iter.times { BufferBench.bench_buffer_inout(0.chr * 4, 0) } + } } -} -puts "Benchmark FFI call(Buffer.alloc_inout(:int, 1, true)) performance, #{iter}x" -10.times { - puts Benchmark.measure { - iter.times { BufferBench.bench_buffer_inout(FFI::Buffer.alloc_inout(:int, 1, true), 0) } + puts "Benchmark FFI call(Buffer.alloc_inout(:int, 1, true)) performance, #{iter}x" + 10.times { + puts Benchmark.measure { + iter.times { BufferBench.bench_buffer_inout(FFI::Buffer.alloc_inout(:int, 1, true), 0) } + } } -} -puts "Benchmark FFI call(Buffer.alloc_inout(IntStruct, 1, true)) performance, #{iter}x" -10.times { - puts Benchmark.measure { - iter.times { BufferBench.bench_buffer_inout(FFI::Buffer.alloc_inout(IntStruct, 1, true), 0) } + puts "Benchmark FFI call(Buffer.alloc_inout(IntStruct, 1, true)) performance, #{iter}x" + 10.times { + puts Benchmark.measure { + iter.times { BufferBench.bench_buffer_inout(FFI::Buffer.alloc_inout(IntStruct, 1, true), 0) } + } } -} -puts "Benchmark FFI call(Buffer.alloc_inout(4, 1, true)) performance, #{iter}x" -10.times { - puts Benchmark.measure { - iter.times { BufferBench.bench_buffer_inout(FFI::Buffer.alloc_inout(4, 1, true), 0) } + puts "Benchmark FFI call(Buffer.alloc_inout(4, 1, true)) performance, #{iter}x" + 10.times { + puts Benchmark.measure { + iter.times { BufferBench.bench_buffer_inout(FFI::Buffer.alloc_inout(4, 1, true), 0) } + } } -} -puts "Benchmark FFI call(Buffer.alloc_in(:int, 1, true)) performance, #{iter}x" -10.times { - puts Benchmark.measure { - iter.times { BufferBench.bench_buffer_in(FFI::Buffer.alloc_in(:int, 1, true), 0) } + puts "Benchmark FFI call(Buffer.alloc_in(:int, 1, true)) performance, #{iter}x" + 10.times { + puts Benchmark.measure { + iter.times { BufferBench.bench_buffer_in(FFI::Buffer.alloc_in(:int, 1, true), 0) } + } } -} -puts "Benchmark FFI call(Buffer.alloc_in(4, 1, true)) performance, #{iter}x" -10.times { - puts Benchmark.measure { - iter.times { BufferBench.bench_buffer_in(FFI::Buffer.alloc_in(4, 1, true), 0) } + puts "Benchmark FFI call(Buffer.alloc_in(4, 1, true)) performance, #{iter}x" + 10.times { + puts Benchmark.measure { + iter.times { BufferBench.bench_buffer_in(FFI::Buffer.alloc_in(4, 1, true), 0) } + } } -} -puts "Benchmark FFI call(Buffer.alloc_in(IntStruct, 1, true)) performance, #{iter}x" -10.times { - puts Benchmark.measure { - iter.times { BufferBench.bench_buffer_in(FFI::Buffer.alloc_in(IntStruct, 1, true), 0) } + puts "Benchmark FFI call(Buffer.alloc_in(IntStruct, 1, true)) performance, #{iter}x" + 10.times { + puts Benchmark.measure { + iter.times { BufferBench.bench_buffer_in(FFI::Buffer.alloc_in(IntStruct, 1, true), 0) } + } } -} -puts "Benchmark FFI call(Buffer.alloc_out(:int, 1, true)) performance, #{iter}x" -10.times { - puts Benchmark.measure { - iter.times { BufferBench.bench_buffer_out(FFI::Buffer.alloc_out(:int, 1, true), 0) } + puts "Benchmark FFI call(Buffer.alloc_out(:int, 1, true)) performance, #{iter}x" + 10.times { + puts Benchmark.measure { + iter.times { BufferBench.bench_buffer_out(FFI::Buffer.alloc_out(:int, 1, true), 0) } + } } -} -puts "Benchmark FFI call(Buffer.alloc_out(IntStruct, 1, true)) performance, #{iter}x" -10.times { - puts Benchmark.measure { - iter.times { BufferBench.bench_buffer_out(FFI::Buffer.alloc_out(IntStruct, 1, true), 0) } + puts "Benchmark FFI call(Buffer.alloc_out(IntStruct, 1, true)) performance, #{iter}x" + 10.times { + puts Benchmark.measure { + iter.times { BufferBench.bench_buffer_out(FFI::Buffer.alloc_out(IntStruct, 1, true), 0) } + } } -} -puts "Benchmark FFI call(Buffer.alloc_out(4, 1, true)) performance, #{iter}x" -10.times { - puts Benchmark.measure { - iter.times { BufferBench.bench_buffer_out(FFI::Buffer.alloc_out(4, 1, true), 0) } + puts "Benchmark FFI call(Buffer.alloc_out(4, 1, true)) performance, #{iter}x" + 10.times { + puts Benchmark.measure { + iter.times { BufferBench.bench_buffer_out(FFI::Buffer.alloc_out(4, 1, true), 0) } + } } -} +end diff --git a/bench/bench_buffer_alloc.rb b/bench/bench_buffer_alloc.rb index 0f223ffe0..6314b6328 100644 --- a/bench/bench_buffer_alloc.rb +++ b/bench/bench_buffer_alloc.rb @@ -1,43 +1,45 @@ require_relative 'bench_helper' -iter = ITER +module BenchBufferAlloc + iter = ITER -puts "Benchmark Buffer.new(:int, 1, true)) performance, #{iter}x" -10.times { - puts Benchmark.measure { - i = 0; while i < iter - FFI::Buffer.new(:int, 1, true) - i += 1 - end + puts "Benchmark Buffer.new(:int, 1, true)) performance, #{iter}x" + 10.times { + puts Benchmark.measure { + i = 0; while i < iter + FFI::Buffer.new(:int, 1, true) + i += 1 + end + } } -} -puts "Benchmark Buffer.alloc_out(:int, 1, true)) performance, #{iter}x" -10.times { - puts Benchmark.measure { - i = 0; while i < iter - FFI::Buffer.new_out(:int, 1, true) - i += 1 - end + puts "Benchmark Buffer.alloc_out(:int, 1, true)) performance, #{iter}x" + 10.times { + puts Benchmark.measure { + i = 0; while i < iter + FFI::Buffer.new_out(:int, 1, true) + i += 1 + end + } } -} -puts "Benchmark Buffer.new(4, 1, true)) performance, #{iter}x" -10.times { - puts Benchmark.measure { - i = 0; while i < iter - FFI::Buffer.new(4, 1, true) - i += 1 - end + puts "Benchmark Buffer.new(4, 1, true)) performance, #{iter}x" + 10.times { + puts Benchmark.measure { + i = 0; while i < iter + FFI::Buffer.new(4, 1, true) + i += 1 + end + } } -} -puts "Benchmark Buffer.new(256, 1, true)) performance, #{iter}x" -10.times { - puts Benchmark.measure { - i = 0; while i < iter - FFI::Buffer.new(256, 1, true) - i += 1 - end + puts "Benchmark Buffer.new(256, 1, true)) performance, #{iter}x" + 10.times { + puts Benchmark.measure { + i = 0; while i < iter + FFI::Buffer.new(256, 1, true) + i += 1 + end + } } -} +end diff --git a/bench/bench_buffer_fill.rb b/bench/bench_buffer_fill.rb index 66e6efd35..259a6ae90 100644 --- a/bench/bench_buffer_fill.rb +++ b/bench/bench_buffer_fill.rb @@ -1,43 +1,45 @@ require_relative 'bench_helper' -iter = ITER +module BenchBufferFill + iter = ITER -puts "Benchmark Buffer#put_array_of_float performance, #{iter}x" + puts "Benchmark Buffer#put_array_of_float performance, #{iter}x" -5.times { - ptr = FFI::Buffer.new(:float, 8, false) - puts Benchmark.measure { - iter.times { - ptr.put_array_of_float(0, [ 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8 ]) + 5.times { + ptr = FFI::Buffer.new(:float, 8, false) + puts Benchmark.measure { + iter.times { + ptr.put_array_of_float(0, [ 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8 ]) + } } } -} -puts "Benchmark Buffer.new(:float, 8, false)).put_array_of_float performance, #{iter}x" -5.times { - puts Benchmark.measure { - iter.times { - ptr = FFI::Buffer.new(:float, 8, false) - ptr.put_array_of_float(0, [ 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8 ]) + puts "Benchmark Buffer.new(:float, 8, false)).put_array_of_float performance, #{iter}x" + 5.times { + puts Benchmark.measure { + iter.times { + ptr = FFI::Buffer.new(:float, 8, false) + ptr.put_array_of_float(0, [ 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8 ]) + } } } -} -module LibTest - extend FFI::Library - ffi_lib LIBTEST_PATH - - attach_function :bench, :bench_P_v, [ :buffer_in ], :void -end - -puts "Benchmark Buffer alloc+fill+call performance, #{iter}x" -5.times { - puts Benchmark.measure { - iter.times { - ptr = FFI::Buffer.new(:float, 8, false) - ptr.put_array_of_float(0, [ 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8 ]) - LibTest.bench(ptr) + module LibTest + extend FFI::Library + ffi_lib LIBTEST_PATH + + attach_function :bench, :bench_P_v, [ :buffer_in ], :void + end + + puts "Benchmark Buffer alloc+fill+call performance, #{iter}x" + 5.times { + puts Benchmark.measure { + iter.times { + ptr = FFI::Buffer.new(:float, 8, false) + ptr.put_array_of_float(0, [ 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8 ]) + LibTest.bench(ptr) + } } } -} +end diff --git a/bench/bench_chmod.rb b/bench/bench_chmod.rb index c0b683845..71b3576d3 100644 --- a/bench/bench_chmod.rb +++ b/bench/bench_chmod.rb @@ -1,34 +1,36 @@ require_relative 'bench_helper' -iter = ITER -file = "README" +module BenchChmod + iter = ITER + file = "README" -module Posix - extend FFI::Library - ffi_lib FFI::Library::LIBC + module Posix + extend FFI::Library + ffi_lib FFI::Library::LIBC - def self.chmod(mode, path) - if self._chmod(path, mode) != 0 + def self.chmod(mode, path) + if self._chmod(path, mode) != 0 + end + end + if FFI::Platform.windows? + attach_function :_chmod, :_chmod, [ :string, :int ], :int + else + attach_function :_chmod, :chmod, [ :string, :int ], :int end end - if FFI::Platform.windows? - attach_function :_chmod, :_chmod, [ :string, :int ], :int - else - attach_function :_chmod, :chmod, [ :string, :int ], :int - end -end -puts "Benchmark FFI chmod performance, #{iter}x changing mode" -10.times { - puts Benchmark.measure { - iter.times { Posix.chmod(0622, __FILE__) } + puts "Benchmark FFI chmod performance, #{iter}x changing mode" + 10.times { + puts Benchmark.measure { + iter.times { Posix.chmod(0622, __FILE__) } + } } -} -puts "Benchmark Ruby File.chmod performance, #{iter}x changing mode" -10.times { - puts Benchmark.measure { - iter.times { File.chmod(0622, __FILE__) } + puts "Benchmark Ruby File.chmod performance, #{iter}x changing mode" + 10.times { + puts Benchmark.measure { + iter.times { File.chmod(0622, __FILE__) } + } } -} +end diff --git a/bench/bench_closure_IIIrV.rb b/bench/bench_closure_IIIrV.rb index 1c164f279..1ecb3f339 100644 --- a/bench/bench_closure_IIIrV.rb +++ b/bench/bench_closure_IIIrV.rb @@ -1,67 +1,69 @@ require_relative 'bench_helper' -module LibTest - extend FFI::Library - ffi_lib LIBTEST_PATH - callback :closureIIIrV, [ :int, :int, :int ], :void - attach_function :ffi_bench, :testClosureIIIrV, [ :closureIIIrV, :int, :int, :int ], :void - def self.rb_bench(a, b, c, &block); yield(a, b, c); end -end +module BenchClosureIIIrV + module LibTest + extend FFI::Library + ffi_lib LIBTEST_PATH + callback :closureIIIrV, [ :int, :int, :int ], :void + attach_function :ffi_bench, :testClosureIIIrV, [ :closureIIIrV, :int, :int, :int ], :void + def self.rb_bench(a, b, c, &block); yield(a, b, c); end + end -class Foo - def call(a, b, c); nil; end -end + class Foo + def call(a, b, c); nil; end + end -puts "Benchmark [ ], :void closure block, #{ITER}x calls" -10.times { - puts Benchmark.measure { - ITER.times { LibTest.ffi_bench(1, 2, 3) { } } + puts "Benchmark [ ], :void closure block, #{ITER}x calls" + 10.times { + puts Benchmark.measure { + ITER.times { LibTest.ffi_bench(1, 2, 3) { } } + } } -} -puts "Benchmark [ ], :void closure callable, #{ITER}x calls" -10.times { - puts Benchmark.measure { - ITER.times { LibTest.ffi_bench(Foo.new, 1, 2, 3) } + puts "Benchmark [ ], :void closure callable, #{ITER}x calls" + 10.times { + puts Benchmark.measure { + ITER.times { LibTest.ffi_bench(Foo.new, 1, 2, 3) } + } } -} -puts "Benchmark [ ], :void pre-allocated function with block, #{ITER}x calls" -10.times { - fn = FFI::Function.new(:void, [ :int, :int, :int ]) {} - puts Benchmark.measure { - ITER.times { LibTest.ffi_bench(fn, 1, 2, 3) } + puts "Benchmark [ ], :void pre-allocated function with block, #{ITER}x calls" + 10.times { + fn = FFI::Function.new(:void, [ :int, :int, :int ]) {} + puts Benchmark.measure { + ITER.times { LibTest.ffi_bench(fn, 1, 2, 3) } + } } -} -puts "Benchmark [ ], :void pre-allocated function with callable, #{ITER}x calls" -10.times { - fn = FFI::Function.new(:void, [ :int, :int, :int ], Foo.new) - puts Benchmark.measure { - ITER.times { LibTest.ffi_bench(fn, 1, 2, 3) } + puts "Benchmark [ ], :void pre-allocated function with callable, #{ITER}x calls" + 10.times { + fn = FFI::Function.new(:void, [ :int, :int, :int ], Foo.new) + puts Benchmark.measure { + ITER.times { LibTest.ffi_bench(fn, 1, 2, 3) } + } } -} -puts "Benchmark [ ], :void pre-allocated proc, #{ITER}x calls" -10.times { - proc = lambda { |a,b,c| } - puts Benchmark.measure { - ITER.times { LibTest.ffi_bench(proc, 1, 2, 3) } + puts "Benchmark [ ], :void pre-allocated proc, #{ITER}x calls" + 10.times { + proc = lambda { |a,b,c| } + puts Benchmark.measure { + ITER.times { LibTest.ffi_bench(proc, 1, 2, 3) } + } } -} -puts "Benchmark [ ], :void pre-allocated callable, #{ITER}x calls" -10.times { - proc = Foo.new - puts Benchmark.measure { - ITER.times { LibTest.ffi_bench(proc, 1, 2, 3) } + puts "Benchmark [ ], :void pre-allocated callable, #{ITER}x calls" + 10.times { + proc = Foo.new + puts Benchmark.measure { + ITER.times { LibTest.ffi_bench(proc, 1, 2, 3) } + } } -} -puts "Benchmark ruby method(3 arg), #{ITER}x calls" -10.times { - puts Benchmark.measure { - ITER.times { LibTest.rb_bench(1, 2, 3) {} } + puts "Benchmark ruby method(3 arg), #{ITER}x calls" + 10.times { + puts Benchmark.measure { + ITER.times { LibTest.rb_bench(1, 2, 3) {} } + } } -} + end diff --git a/bench/bench_closure_IrV.rb b/bench/bench_closure_IrV.rb index 0e4021eab..33fb06482 100644 --- a/bench/bench_closure_IrV.rb +++ b/bench/bench_closure_IrV.rb @@ -1,39 +1,41 @@ require_relative 'bench_helper' -module LibTest - extend FFI::Library - ffi_lib LIBTEST_PATH - callback :closureVrV, [ ], :void - attach_function :ffi_bench, :testClosureIrV, [ :closureVrV, :int ], :void - def self.rb_bench(i, &block); nil; end -end +module BenchClosureIrV + module LibTest + extend FFI::Library + ffi_lib LIBTEST_PATH + callback :closureVrV, [ ], :void + attach_function :ffi_bench, :testClosureIrV, [ :closureVrV, :int ], :void + def self.rb_bench(i, &block); nil; end + end -puts "Benchmark [ ], :void closure block performance, #{ITER}x calls" -10.times { - puts Benchmark.measure { - ITER.times { LibTest.ffi_bench(1) { |i| } } + puts "Benchmark [ ], :void closure block performance, #{ITER}x calls" + 10.times { + puts Benchmark.measure { + ITER.times { LibTest.ffi_bench(1) { |i| } } + } } -} -puts "Benchmark [ ], :void pre-allocated function performance, #{ITER}x calls" -10.times { - fn = FFI::Function.new(:void, [ :int ]) { |i| } - puts Benchmark.measure { - ITER.times { LibTest.ffi_bench(fn, 2) } + puts "Benchmark [ ], :void pre-allocated function performance, #{ITER}x calls" + 10.times { + fn = FFI::Function.new(:void, [ :int ]) { |i| } + puts Benchmark.measure { + ITER.times { LibTest.ffi_bench(fn, 2) } + } } -} -puts "Benchmark [ ], :void pre-allocated callable performance, #{ITER}x calls" -10.times { - fn = Proc.new { |i| } - puts Benchmark.measure { - ITER.times { LibTest.ffi_bench(fn, 2) } + puts "Benchmark [ ], :void pre-allocated callable performance, #{ITER}x calls" + 10.times { + fn = Proc.new { |i| } + puts Benchmark.measure { + ITER.times { LibTest.ffi_bench(fn, 2) } + } } -} -puts "Benchmark ruby method(1 arg) performance, #{ITER}x calls" -10.times { - puts Benchmark.measure { - ITER.times { LibTest.rb_bench(1) {} } + puts "Benchmark ruby method(1 arg) performance, #{ITER}x calls" + 10.times { + puts Benchmark.measure { + ITER.times { LibTest.rb_bench(1) {} } + } } -} + end diff --git a/bench/bench_closure_VrV.rb b/bench/bench_closure_VrV.rb index c8239f992..eb2992e43 100644 --- a/bench/bench_closure_VrV.rb +++ b/bench/bench_closure_VrV.rb @@ -1,53 +1,55 @@ require_relative 'bench_helper' -module LibTest - extend FFI::Library - ffi_lib LIBTEST_PATH - callback :closureVrV, [ ], :void - - attach_function :ffi_bench, :testClosureVrV, [ :closureVrV ], :void - @blocking = true - attach_function :threaded_bench, :testThreadedClosureVrV, [ :closureVrV, :int ], :void - - def self.rb_bench(&block) - yield +module BenchClosureVrV + module LibTest + extend FFI::Library + ffi_lib LIBTEST_PATH + callback :closureVrV, [ ], :void + + attach_function :ffi_bench, :testClosureVrV, [ :closureVrV ], :void + @blocking = true + attach_function :threaded_bench, :testThreadedClosureVrV, [ :closureVrV, :int ], :void + + def self.rb_bench(&block) + yield + end end -end -puts "Benchmark [ ], :void closure block performance, #{ITER}x calls" -10.times { - puts Benchmark.measure { - ITER.times { LibTest.ffi_bench { } } + puts "Benchmark [ ], :void closure block performance, #{ITER}x calls" + 10.times { + puts Benchmark.measure { + ITER.times { LibTest.ffi_bench { } } + } } -} -puts "Benchmark [ ], :void pre-allocated function pointer performance, #{ITER}x calls" -10.times { - fn = FFI::Function.new(:void, []) {} - puts Benchmark.measure { - ITER.times { LibTest.ffi_bench fn } + puts "Benchmark [ ], :void pre-allocated function pointer performance, #{ITER}x calls" + 10.times { + fn = FFI::Function.new(:void, []) {} + puts Benchmark.measure { + ITER.times { LibTest.ffi_bench fn } + } } -} -puts "Benchmark [ ], :void pre-allocated closure performance, #{ITER}x calls" -10.times { - proc = lambda {} - puts Benchmark.measure { - ITER.times { LibTest.ffi_bench proc } + puts "Benchmark [ ], :void pre-allocated closure performance, #{ITER}x calls" + 10.times { + proc = lambda {} + puts Benchmark.measure { + ITER.times { LibTest.ffi_bench proc } + } } -} -puts "Benchmark [ ], :void non-ruby thread closure performance, #{ITER}x calls" -10.times { - fn = FFI::Function.new(:void, []) {} - puts Benchmark.measure { - LibTest.threaded_bench(fn, ITER) + puts "Benchmark [ ], :void non-ruby thread closure performance, #{ITER}x calls" + 10.times { + fn = FFI::Function.new(:void, []) {} + puts Benchmark.measure { + LibTest.threaded_bench(fn, ITER) + } } -} -puts "Benchmark ruby method(no arg) performance, #{ITER}x calls" -10.times { - puts Benchmark.measure { - ITER.times { LibTest.rb_bench {} } + puts "Benchmark ruby method(no arg) performance, #{ITER}x calls" + 10.times { + puts Benchmark.measure { + ITER.times { LibTest.rb_bench {} } + } } -} +end diff --git a/bench/bench_enum.rb b/bench/bench_enum.rb index e4d217d8f..21b4de0c9 100644 --- a/bench/bench_enum.rb +++ b/bench/bench_enum.rb @@ -1,45 +1,47 @@ require_relative 'bench_helper' -module LibTest - extend FFI::Library - ffi_lib LIBTEST_PATH - enum :foo, [ :a, :b, :c ] - attach_function :ffi_bench, :bench_s32_v, [ :foo ], :void, :save_errno => false - attach_function :ffi_bench_i, :bench_s32_v, [ :int ], :void, :save_errno => false - def self.rb_bench(i0); nil; end -end +module BenchEnum + module LibTest + extend FFI::Library + ffi_lib LIBTEST_PATH + enum :foo, [ :a, :b, :c ] + attach_function :ffi_bench, :bench_s32_v, [ :foo ], :void, :save_errno => false + attach_function :ffi_bench_i, :bench_s32_v, [ :int ], :void, :save_errno => false + def self.rb_bench(i0); nil; end + end -puts "Benchmark [ enum ], :void performance, #{ITER}x calls" -10.times { - puts Benchmark.measure { - ITER.times { LibTest.ffi_bench(:a) } + puts "Benchmark [ enum ], :void performance, #{ITER}x calls" + 10.times { + puts Benchmark.measure { + ITER.times { LibTest.ffi_bench(:a) } + } } -} -puts "Benchmark [ enum ], :void with int arg performance, #{ITER}x calls" -10.times { - puts Benchmark.measure { - ITER.times { LibTest.ffi_bench(1) } + puts "Benchmark [ enum ], :void with int arg performance, #{ITER}x calls" + 10.times { + puts Benchmark.measure { + ITER.times { LibTest.ffi_bench(1) } + } } -} -puts "Benchmark [ :int ], :void performance, #{ITER}x calls" -10.times { - puts Benchmark.measure { - ITER.times { LibTest.ffi_bench_i(1) } + puts "Benchmark [ :int ], :void performance, #{ITER}x calls" + 10.times { + puts Benchmark.measure { + ITER.times { LibTest.ffi_bench_i(1) } + } } -} -puts "Benchmark [ :int ], :void with enum arg performance, #{ITER}x calls" -10.times { - puts Benchmark.measure { - ITER.times { LibTest.ffi_bench_i(:a) } + puts "Benchmark [ :int ], :void with enum arg performance, #{ITER}x calls" + 10.times { + puts Benchmark.measure { + ITER.times { LibTest.ffi_bench_i(:a) } + } } -} -puts "Benchmark ruby method(1 arg) performance, #{ITER}x calls" -10.times { - puts Benchmark.measure { - ITER.times { LibTest.rb_bench(:a) } + puts "Benchmark ruby method(1 arg) performance, #{ITER}x calls" + 10.times { + puts Benchmark.measure { + ITER.times { LibTest.rb_bench(:a) } + } } -} +end diff --git a/bench/bench_enum_i.rb b/bench/bench_enum_i.rb index a249274df..8a5b6da54 100644 --- a/bench/bench_enum_i.rb +++ b/bench/bench_enum_i.rb @@ -1,17 +1,19 @@ require_relative 'bench_helper' -module LibTest - extend FFI::Library - ffi_lib LIBTEST_PATH - enum :foo, [ :a, :b, :c ] - attach_function :ffi_bench, :bench_s32_v, [ :foo ], :void, :save_errno => true - attach_function :ffi_bench_i, :bench_s32_v, [ :int ], :void, :save_errno => true - def self.rb_bench(i0); nil; end -end +module BenchEnumI + module LibTest + extend FFI::Library + ffi_lib LIBTEST_PATH + enum :foo, [ :a, :b, :c ] + attach_function :ffi_bench, :bench_s32_v, [ :foo ], :void, :save_errno => true + attach_function :ffi_bench_i, :bench_s32_v, [ :int ], :void, :save_errno => true + def self.rb_bench(i0); nil; end + end -puts "Benchmark [ :int ], :void performance, #{ITER}x calls" -10.times { - puts Benchmark.measure { - ITER.times { LibTest.ffi_bench_i(1) } + puts "Benchmark [ :int ], :void performance, #{ITER}x calls" + 10.times { + puts Benchmark.measure { + ITER.times { LibTest.ffi_bench_i(1) } + } } -} +end diff --git a/bench/bench_getlogin.rb b/bench/bench_getlogin.rb index ca2815162..c5824f4e1 100644 --- a/bench/bench_getlogin.rb +++ b/bench/bench_getlogin.rb @@ -1,28 +1,30 @@ require_relative 'bench_helper' require 'etc' -iter = ITER +module BenchGetlogin + iter = ITER -module Posix - extend FFI::Library - ffi_lib FFI::Library::LIBC - attach_function :getlogin, [], :string -end -if Posix.getlogin != Etc.getlogin - raise ArgumentError, "FFI getlogin returned incorrect value" -end + module Posix + extend FFI::Library + ffi_lib FFI::Library::LIBC + attach_function :getlogin, [], :string + end + if Posix.getlogin != Etc.getlogin + raise ArgumentError, "FFI getlogin returned incorrect value" + end -puts "Benchmark FFI getlogin(2) performance, #{ITER}x" + puts "Benchmark FFI getlogin(2) performance, #{ITER}x" -10.times { - puts Benchmark.measure { - iter.times { Posix.getlogin } + 10.times { + puts Benchmark.measure { + iter.times { Posix.getlogin } + } } -} -puts "Benchmark Etc.getlogin performance, #{ITER}x" -10.times { - puts Benchmark.measure { - iter.times { Etc.getlogin } + puts "Benchmark Etc.getlogin performance, #{ITER}x" + 10.times { + puts Benchmark.measure { + iter.times { Etc.getlogin } + } } -} +end diff --git a/bench/bench_getpid.rb b/bench/bench_getpid.rb index e2f468cd0..3cb391e46 100644 --- a/bench/bench_getpid.rb +++ b/bench/bench_getpid.rb @@ -1,34 +1,36 @@ require_relative 'bench_helper' -iter = ITER +module BenchGetpid + iter = ITER -module Posix - extend FFI::Library - ffi_lib 'c' - if FFI::Platform.windows? - attach_function :getpid, :_getpid, [], :uint, :save_errno => false - else - attach_function :getpid, [], :uint, :save_errno => false + module Posix + extend FFI::Library + ffi_lib 'c' + if FFI::Platform.windows? + attach_function :getpid, :_getpid, [], :uint, :save_errno => false + else + attach_function :getpid, [], :uint, :save_errno => false + end end -end -puts "pid=#{Process.pid} Foo.getpid=#{Posix.getpid}" -puts "Benchmark FFI getpid performance, #{iter}x calls" -10.times { - puts Benchmark.measure { - i = 0; while i < iter - Posix.getpid - i += 1 - end + puts "pid=#{Process.pid} Foo.getpid=#{Posix.getpid}" + puts "Benchmark FFI getpid performance, #{iter}x calls" + 10.times { + puts Benchmark.measure { + i = 0; while i < iter + Posix.getpid + i += 1 + end + } } -} -puts "Benchmark Process.pid performance, #{iter}x calls" -10.times { - puts Benchmark.measure { - i = 0; while i < iter - Process.pid - i += 1 - end + puts "Benchmark Process.pid performance, #{iter}x calls" + 10.times { + puts Benchmark.measure { + i = 0; while i < iter + Process.pid + i += 1 + end + } } -} +end diff --git a/bench/bench_gettimeofday.rb b/bench/bench_gettimeofday.rb index 69f801ba8..5884d76c3 100644 --- a/bench/bench_gettimeofday.rb +++ b/bench/bench_gettimeofday.rb @@ -1,51 +1,53 @@ require_relative 'bench_helper' -module Posix - extend FFI::Library - ffi_lib FFI::Library::LIBC +module BenchGettimeofday + module Posix + extend FFI::Library + ffi_lib FFI::Library::LIBC - attach_function :gettimeofday, [ :buffer_out, :pointer ], :int -end -class Timeval < FFI::Struct - layout :tv_sec, :ulong, :tv_nsec, :ulong -end + attach_function :gettimeofday, [ :buffer_out, :pointer ], :int + end + class Timeval < FFI::Struct + layout :tv_sec, :ulong, :tv_nsec, :ulong + end -iter = ITER -puts "Benchmark FFI gettimeofday(2) (nil, nil) performance, #{iter}x" + iter = ITER + puts "Benchmark FFI gettimeofday(2) (nil, nil) performance, #{iter}x" -10.times { - puts Benchmark.measure { - iter.times { Posix.gettimeofday(nil, nil) } + 10.times { + puts Benchmark.measure { + iter.times { Posix.gettimeofday(nil, nil) } + } } -} -puts "Benchmark FFI gettimeofday(2) (Timeval.alloc_out, nil) performance, #{iter}x" -10.times { - puts Benchmark.measure { - iter.times { Posix.gettimeofday(Timeval.alloc_out, nil) } + puts "Benchmark FFI gettimeofday(2) (Timeval.alloc_out, nil) performance, #{iter}x" + 10.times { + puts Benchmark.measure { + iter.times { Posix.gettimeofday(Timeval.alloc_out, nil) } + } } -} -puts "Benchmark FFI gettimeofday(2) (Timeval.new(FFI::MemoryPointer.new), nil) performance, #{iter}x" -10.times { - puts Benchmark.measure { - iter.times { Posix.gettimeofday(Timeval.new(FFI::MemoryPointer.new(Timeval)), nil) } + puts "Benchmark FFI gettimeofday(2) (Timeval.new(FFI::MemoryPointer.new), nil) performance, #{iter}x" + 10.times { + puts Benchmark.measure { + iter.times { Posix.gettimeofday(Timeval.new(FFI::MemoryPointer.new(Timeval)), nil) } + } } -} -puts "Benchmark FFI gettimeofday(2) (Timeval.new(FFI::Buffer.new), nil) performance, #{iter}x" -10.times { - puts Benchmark.measure { - iter.times { Posix.gettimeofday(Timeval.new(FFI::Buffer.new(Timeval)), nil) } + puts "Benchmark FFI gettimeofday(2) (Timeval.new(FFI::Buffer.new), nil) performance, #{iter}x" + 10.times { + puts Benchmark.measure { + iter.times { Posix.gettimeofday(Timeval.new(FFI::Buffer.new(Timeval)), nil) } + } } -} -puts "Benchmark FFI gettimeofday(2) (pre allocated pointer, nil) performance, #{iter}x" -10.times { - t = Timeval.new FFI::MemoryPointer.new(Timeval) - puts Benchmark.measure { - iter.times { Posix.gettimeofday(t, nil) } + puts "Benchmark FFI gettimeofday(2) (pre allocated pointer, nil) performance, #{iter}x" + 10.times { + t = Timeval.new FFI::MemoryPointer.new(Timeval) + puts Benchmark.measure { + iter.times { Posix.gettimeofday(t, nil) } + } } -} -puts "Benchmark Time.now performance, #{iter}x" -10.times { - puts Benchmark.measure { - iter.times { Time.now } + puts "Benchmark Time.now performance, #{iter}x" + 10.times { + puts Benchmark.measure { + iter.times { Time.now } + } } -} +end diff --git a/bench/bench_getuid.rb b/bench/bench_getuid.rb index 8a5719a08..25aec5398 100644 --- a/bench/bench_getuid.rb +++ b/bench/bench_getuid.rb @@ -1,25 +1,27 @@ require_relative 'bench_helper' -iter = ITER +module BenchGetuid + iter = ITER -module Posix - extend FFI::Library - ffi_lib FFI::Library::LIBC - attach_function :getuid, [], :uint -end + module Posix + extend FFI::Library + ffi_lib FFI::Library::LIBC + attach_function :getuid, [], :uint + end -puts "uid=#{Process.pid} Posix.getuid=#{Posix.getuid}" -puts "Benchmark FFI getuid performance, #{iter}x calls" + puts "uid=#{Process.pid} Posix.getuid=#{Posix.getuid}" + puts "Benchmark FFI getuid performance, #{iter}x calls" -10.times { - puts Benchmark.measure { - iter.times { Posix.getuid } + 10.times { + puts Benchmark.measure { + iter.times { Posix.getuid } + } } -} -puts "Benchmark Process.uid performance, #{iter}x calls" -10.times { - puts Benchmark.measure { - iter.times { Process.uid } + puts "Benchmark Process.uid performance, #{iter}x calls" + 10.times { + puts Benchmark.measure { + iter.times { Process.uid } + } } -} +end diff --git a/bench/bench_math.rb b/bench/bench_math.rb index 64796b8f2..bea286840 100644 --- a/bench/bench_math.rb +++ b/bench/bench_math.rb @@ -1,30 +1,32 @@ require_relative 'bench_helper' -module FFIMath - extend FFI::Library - ffi_lib 'm' - attach_function :cos, [ :double ], :double - attach_function :cosf, [ :float ], :float -end -if FFIMath.cos(0) != 1 - raise ArgumentError, "FFI.cos returned incorrect value" -end -puts "Benchmark FFI cos(0) performance, #{ITER}x" -10.times { - puts Benchmark.measure { - ITER.times { FFIMath.cos(0) } +module BenchMath + module FFIMath + extend FFI::Library + ffi_lib 'm' + attach_function :cos, [ :double ], :double + attach_function :cosf, [ :float ], :float + end + if FFIMath.cos(0) != 1 + raise ArgumentError, "FFI.cos returned incorrect value" + end + puts "Benchmark FFI cos(0) performance, #{ITER}x" + 10.times { + puts Benchmark.measure { + ITER.times { FFIMath.cos(0) } + } } -} -puts "Benchmark FFI cosf(0) performance, #{ITER}x" -10.times { - puts Benchmark.measure { - ITER.times { FFIMath.cosf(0) } + puts "Benchmark FFI cosf(0) performance, #{ITER}x" + 10.times { + puts Benchmark.measure { + ITER.times { FFIMath.cosf(0) } + } } -} -puts "Benchmark Math.cos(0) performance, #{ITER}x" -10.times { - puts Benchmark.measure { - ITER.times { Math.cos(0) } + puts "Benchmark Math.cos(0) performance, #{ITER}x" + 10.times { + puts Benchmark.measure { + ITER.times { Math.cos(0) } + } } -} +end diff --git a/bench/bench_memptr_alloc.rb b/bench/bench_memptr_alloc.rb index a6002abf6..446773350 100644 --- a/bench/bench_memptr_alloc.rb +++ b/bench/bench_memptr_alloc.rb @@ -1,59 +1,61 @@ require_relative 'bench_helper' -iter = ITER +module BenchMemptrAlloc + iter = ITER -module LibC - extend FFI::Library - ffi_lib 'c' - attach_function :calloc, [ :size_t, :size_t ], :pointer, :save_errno => false - attach_function :free, [ :pointer ], :void, :save_errno => false -end + module LibC + extend FFI::Library + ffi_lib 'c' + attach_function :calloc, [ :size_t, :size_t ], :pointer, :save_errno => false + attach_function :free, [ :pointer ], :void, :save_errno => false + end -puts "Benchmark calloc(1, 4) performance, #{iter}x" -10.times { - puts Benchmark.measure { - i = 0; while i < iter - ptr = LibC.calloc(1, 4) - LibC.free(ptr) - i += 1 - end - } -} -puts "Benchmark MemoryPointer.new(:int, 1, true)) performance, #{iter}x" -10.times { - puts Benchmark.measure { - i = 0; while i < iter - FFI::MemoryPointer.new(:int) - i += 1 - end + puts "Benchmark calloc(1, 4) performance, #{iter}x" + 10.times { + puts Benchmark.measure { + i = 0; while i < iter + ptr = LibC.calloc(1, 4) + LibC.free(ptr) + i += 1 + end + } } -} -puts "Benchmark MemoryPointer.new(4, 1, true)) performance, #{iter}x" -10.times { - puts Benchmark.measure { - i = 0; while i < iter - FFI::MemoryPointer.new(4, 1, true) - i += 1 - end + puts "Benchmark MemoryPointer.new(:int, 1, true)) performance, #{iter}x" + 10.times { + puts Benchmark.measure { + i = 0; while i < iter + FFI::MemoryPointer.new(:int) + i += 1 + end + } } -} -[ 8, 16, 32, 64, 128, 256 ].each do |size| -puts "Benchmark MemoryPointer.new(#{size}, 1, true)) performance, #{iter}x" -10.times { - puts Benchmark.measure { - i = 0; while i < iter - FFI::MemoryPointer.new(size, 1, true) - i += 1 - end + puts "Benchmark MemoryPointer.new(4, 1, true)) performance, #{iter}x" + 10.times { + puts Benchmark.measure { + i = 0; while i < iter + FFI::MemoryPointer.new(4, 1, true) + i += 1 + end + } } -} -end - -if defined?(RUBY_ENGINE) && RUBY_ENGINE == "jruby" - require 'java' - puts "calling java gc" + [ 8, 16, 32, 64, 128, 256 ].each do |size| + puts "Benchmark MemoryPointer.new(#{size}, 1, true)) performance, #{iter}x" 10.times { - java.lang.System.gc - sleep 1 + puts Benchmark.measure { + i = 0; while i < iter + FFI::MemoryPointer.new(size, 1, true) + i += 1 + end + } } + end + + if defined?(RUBY_ENGINE) && RUBY_ENGINE == "jruby" + require 'java' + puts "calling java gc" + 10.times { + java.lang.System.gc + sleep 1 + } + end end diff --git a/bench/bench_memptr_fill.rb b/bench/bench_memptr_fill.rb index 74a940aaa..f80f9d3fc 100644 --- a/bench/bench_memptr_fill.rb +++ b/bench/bench_memptr_fill.rb @@ -1,43 +1,45 @@ require_relative 'bench_helper' -iter = ITER +module BenchMemptrFill + iter = ITER -puts "Benchmark MemoryPointer#put_array_of_float performance, #{iter}x" + puts "Benchmark MemoryPointer#put_array_of_float performance, #{iter}x" -5.times { - ptr = FFI::MemoryPointer.new(:float, 8, false) - puts Benchmark.measure { - iter.times { - ptr.put_array_of_float(0, [ 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8 ]) + 5.times { + ptr = FFI::MemoryPointer.new(:float, 8, false) + puts Benchmark.measure { + iter.times { + ptr.put_array_of_float(0, [ 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8 ]) + } } } -} -puts "Benchmark MemoryPointer.new(:float, 8, false)).put_array_of_float performance, #{iter}x" -5.times { - puts Benchmark.measure { - iter.times { - ptr = FFI::MemoryPointer.new(:float, 8, false) - ptr.put_array_of_float(0, [ 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8 ]) + puts "Benchmark MemoryPointer.new(:float, 8, false)).put_array_of_float performance, #{iter}x" + 5.times { + puts Benchmark.measure { + iter.times { + ptr = FFI::MemoryPointer.new(:float, 8, false) + ptr.put_array_of_float(0, [ 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8 ]) + } } } -} -module LibTest - extend FFI::Library - ffi_lib LIBTEST_PATH - - attach_function :bench, :bench_P_v, [ :buffer_in ], :void -end - -puts "Benchmark MemoryPointer alloc+fill+call performance, #{iter}x" -5.times { - puts Benchmark.measure { - iter.times { - ptr = FFI::MemoryPointer.new(:float, 8, false) - ptr.put_array_of_float(0, [ 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8 ]) - LibTest.bench(ptr) + module LibTest + extend FFI::Library + ffi_lib LIBTEST_PATH + + attach_function :bench, :bench_P_v, [ :buffer_in ], :void + end + + puts "Benchmark MemoryPointer alloc+fill+call performance, #{iter}x" + 5.times { + puts Benchmark.measure { + iter.times { + ptr = FFI::MemoryPointer.new(:float, 8, false) + ptr.put_array_of_float(0, [ 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8 ]) + LibTest.bench(ptr) + } } } -} +end diff --git a/bench/bench_strlen.rb b/bench/bench_strlen.rb index 3c8a6488b..9f0264fe4 100644 --- a/bench/bench_strlen.rb +++ b/bench/bench_strlen.rb @@ -1,26 +1,28 @@ require_relative 'bench_helper' -module LibC - extend FFI::Library - ffi_lib 'c' - attach_function :strlen, [ :string ], :int -end +module BenchStrlen + module LibC + extend FFI::Library + ffi_lib 'c' + attach_function :strlen, [ :string ], :int + end -if LibC.strlen("test") != 4 - raise ArgumentError, "FFI.strlen returned incorrect value" -end + if LibC.strlen("test") != 4 + raise ArgumentError, "FFI.strlen returned incorrect value" + end -puts "Benchmark FFI api strlen(3) performance, #{ITER}x" -str = 'test' * 10 -10.times { - puts Benchmark.measure { - ITER.times { LibC.strlen(str) } + puts "Benchmark FFI api strlen(3) performance, #{ITER}x" + str = 'test' * 10 + 10.times { + puts Benchmark.measure { + ITER.times { LibC.strlen(str) } + } } -} -puts "Benchmark FFI api strlen(3), with new string performance, #{ITER}x" -10.times { - puts Benchmark.measure { - ITER.times { LibC.strlen('test' * 10) } + puts "Benchmark FFI api strlen(3), with new string performance, #{ITER}x" + 10.times { + puts Benchmark.measure { + ITER.times { LibC.strlen('test' * 10) } + } } -} +end diff --git a/bench/bench_struct.rb b/bench/bench_struct.rb index 67bde3289..2d5f7b92c 100644 --- a/bench/bench_struct.rb +++ b/bench/bench_struct.rb @@ -1,59 +1,61 @@ require_relative 'bench_helper' -module StructBench - extend FFI::Library - extend FFI::Library - ffi_lib LIBTEST_PATH - attach_function :bench_s32_v, [ :int ], :void - begin - attach_function :bench_struct_in, :ptr_ret_int32_t, [ :buffer_in, :int ], :void - rescue FFI::NotFoundError - # NetBSD uses #define instead of typedef for these - attach_function :bench_struct_in, :ptr_ret___int32_t, [ :buffer_in, :int ], :void - end - begin - attach_function :bench_struct_out, :ptr_ret_int32_t, [ :buffer_out, :int ], :void - rescue FFI::NotFoundError - # NetBSD uses #define instead of typedef for these - attach_function :bench_struct_out, :ptr_ret___int32_t, [ :buffer_out, :int ], :void +module BenchStruct + module StructBench + extend FFI::Library + extend FFI::Library + ffi_lib LIBTEST_PATH + attach_function :bench_s32_v, [ :int ], :void + begin + attach_function :bench_struct_in, :ptr_ret_int32_t, [ :buffer_in, :int ], :void + rescue FFI::NotFoundError + # NetBSD uses #define instead of typedef for these + attach_function :bench_struct_in, :ptr_ret___int32_t, [ :buffer_in, :int ], :void + end + begin + attach_function :bench_struct_out, :ptr_ret_int32_t, [ :buffer_out, :int ], :void + rescue FFI::NotFoundError + # NetBSD uses #define instead of typedef for these + attach_function :bench_struct_out, :ptr_ret___int32_t, [ :buffer_out, :int ], :void + end + begin + attach_function :bench_struct_inout, :ptr_ret_int32_t, [ :buffer_inout, :int ], :void + rescue FFI::NotFoundError + # NetBSD uses #define instead of typedef for these + attach_function :bench_struct_inout, :ptr_ret___int32_t, [ :buffer_inout, :int ], :void + end end - begin - attach_function :bench_struct_inout, :ptr_ret_int32_t, [ :buffer_inout, :int ], :void - rescue FFI::NotFoundError - # NetBSD uses #define instead of typedef for these - attach_function :bench_struct_inout, :ptr_ret___int32_t, [ :buffer_inout, :int ], :void + class TestStruct < FFI::Struct + layout :i, :int, :p, :pointer end -end -class TestStruct < FFI::Struct - layout :i, :int, :p, :pointer -end -puts "Benchmark FFI call(Struct.alloc_in) performance, #{ITER}x" -10.times { - puts Benchmark.measure { - i = 0; while i < ITER - StructBench.bench_struct_in(TestStruct.alloc_in, 0) - i += 1 - end + puts "Benchmark FFI call(Struct.alloc_in) performance, #{ITER}x" + 10.times { + puts Benchmark.measure { + i = 0; while i < ITER + StructBench.bench_struct_in(TestStruct.alloc_in, 0) + i += 1 + end + } } -} -puts "Benchmark FFI call(Struct.alloc_out) performance, #{ITER}x" -10.times { - puts Benchmark.measure { - i = 0; while i < ITER - StructBench.bench_struct_out(TestStruct.alloc_out, 0) - i += 1 - end + puts "Benchmark FFI call(Struct.alloc_out) performance, #{ITER}x" + 10.times { + puts Benchmark.measure { + i = 0; while i < ITER + StructBench.bench_struct_out(TestStruct.alloc_out, 0) + i += 1 + end + } } -} -puts "Benchmark FFI call(Struct.alloc_inout) performance, #{ITER}x" -10.times { - puts Benchmark.measure { - i = 0; while i < ITER - StructBench.bench_struct_inout(TestStruct.alloc_inout, 0) - i += 1 - end + puts "Benchmark FFI call(Struct.alloc_inout) performance, #{ITER}x" + 10.times { + puts Benchmark.measure { + i = 0; while i < ITER + StructBench.bench_struct_inout(TestStruct.alloc_inout, 0) + i += 1 + end + } } -} +end diff --git a/bench/bench_struct_field.rb b/bench/bench_struct_field.rb index 739718c77..d428c4a6e 100644 --- a/bench/bench_struct_field.rb +++ b/bench/bench_struct_field.rb @@ -1,75 +1,77 @@ require_relative 'bench_helper' -iter = ITER +module BenchStructField + iter = ITER -class TestStruct < FFI::Struct - layout :i, :int, :p, :pointer -end + class TestStruct < FFI::Struct + layout :i, :int, :p, :pointer + end -s = TestStruct.new(FFI::MemoryPointer.new(TestStruct)) -puts "Benchmark FFI Struct.get(:int) performance, #{iter}x" -10.times { - puts Benchmark.measure { - i = 0; max = iter / 4; while i < max - s[:i] - s[:i] - s[:i] - s[:i] - i += 1 - end + s = TestStruct.new(FFI::MemoryPointer.new(TestStruct)) + puts "Benchmark FFI Struct.get(:int) performance, #{iter}x" + 10.times { + puts Benchmark.measure { + i = 0; max = iter / 4; while i < max + s[:i] + s[:i] + s[:i] + s[:i] + i += 1 + end + } } -} -puts "Benchmark FFI Struct.put(:int) performance, #{iter}x" -10.times { - puts Benchmark.measure { - i = 0; max = iter / 4; while i < max - s[:i] = 0x12345678 - s[:i] = 0x12345678 - s[:i] = 0x12345678 - s[:i] = 0x12345678 - i += 1 - end + puts "Benchmark FFI Struct.put(:int) performance, #{iter}x" + 10.times { + puts Benchmark.measure { + i = 0; max = iter / 4; while i < max + s[:i] = 0x12345678 + s[:i] = 0x12345678 + s[:i] = 0x12345678 + s[:i] = 0x12345678 + i += 1 + end + } } -} -puts "Benchmark FFI Struct.get(:pointer) performance, #{iter}x" -10.times { - puts Benchmark.measure { - i = 0; max = iter / 4; while i < max - s[:p] - s[:p] - s[:p] - s[:p] - i += 1 - end + puts "Benchmark FFI Struct.get(:pointer) performance, #{iter}x" + 10.times { + puts Benchmark.measure { + i = 0; max = iter / 4; while i < max + s[:p] + s[:p] + s[:p] + s[:p] + i += 1 + end + } } -} -puts "Benchmark FFI Struct.put(:pointer) performance, #{iter}x" -10.times { - p = FFI::MemoryPointer.new :int - puts Benchmark.measure { - i = 0; max = iter / 4; while i < max - s[:p] = p - s[:p] = p - s[:p] = p - s[:p] = p - i += 1 - end + puts "Benchmark FFI Struct.put(:pointer) performance, #{iter}x" + 10.times { + p = FFI::MemoryPointer.new :int + puts Benchmark.measure { + i = 0; max = iter / 4; while i < max + s[:p] = p + s[:p] = p + s[:p] = p + s[:p] = p + i += 1 + end + } } -} -puts "Benchmark FFI Struct.get(:string) performance, #{iter}x" -class StringStruct < FFI::Struct - layout :s, :string -end -10.times { - mp = FFI::MemoryPointer.new 1024 - mp.put_string(0, "Hello, World") - s = StringStruct.new - s.pointer.put_pointer(0, mp) - puts Benchmark.measure { - i = 0; while i < iter - s[:s] - i += 1 - end + puts "Benchmark FFI Struct.get(:string) performance, #{iter}x" + class StringStruct < FFI::Struct + layout :s, :string + end + 10.times { + mp = FFI::MemoryPointer.new 1024 + mp.put_string(0, "Hello, World") + s = StringStruct.new + s.pointer.put_pointer(0, mp) + puts Benchmark.measure { + i = 0; while i < iter + s[:s] + i += 1 + end + } } -} +end diff --git a/bench/bench_struct_size.rb b/bench/bench_struct_size.rb index bcc2c8d25..e099c6537 100644 --- a/bench/bench_struct_size.rb +++ b/bench/bench_struct_size.rb @@ -1,30 +1,31 @@ require_relative 'bench_helper' -iter = ITER +module BenchStructSize + iter = ITER -class TestStruct < FFI::Struct - layout :i, :int, :p, :pointer -end + layout = class TestStruct < FFI::Struct + layout :i, :int, :p, :pointer + end -puts "Benchmark FFI Struct class size performance, #{iter}x" -10.times { - puts Benchmark.measure { - iter.times { TestStruct.size } + puts "Benchmark FFI Struct class size performance, #{iter}x" + 10.times { + puts Benchmark.measure { + iter.times { TestStruct.size } + } } -} -s = TestStruct.new(FFI::MemoryPointer.new(TestStruct)) -puts "Benchmark FFI Struct instance size performance, #{iter}x" -10.times { - puts Benchmark.measure { - iter.times { s.size } + s = TestStruct.new(FFI::MemoryPointer.new(TestStruct)) + puts "Benchmark FFI Struct instance size performance, #{iter}x" + 10.times { + puts Benchmark.measure { + iter.times { s.size } + } } -} -puts "Benchmark FFI Struct layout size performance, #{iter}x" -layout = TestStruct.layout -10.times { - puts Benchmark.measure { - iter.times { layout.size } + puts "Benchmark FFI Struct layout size performance, #{iter}x" + 10.times { + puts Benchmark.measure { + iter.times { layout.size } + } } -} +end diff --git a/bench/bench_time.rb b/bench/bench_time.rb index 8d3aceb6a..8a06dc943 100644 --- a/bench/bench_time.rb +++ b/bench/bench_time.rb @@ -1,45 +1,47 @@ require_relative 'bench_helper' -module Posix - extend FFI::Library - ffi_lib FFI::Library::LIBC - attach_function :time, [ :buffer_out ], :ulong, :ignore_error => true -end +module BenchTime + module Posix + extend FFI::Library + ffi_lib FFI::Library::LIBC + attach_function :time, [ :buffer_out ], :ulong, :ignore_error => true + end -puts "Benchmark FFI time(3) with nil argument performance, #{ITER}x" -10.times { - puts Benchmark.measure { - ITER.times { Posix.time(nil) } + puts "Benchmark FFI time(3) with nil argument performance, #{ITER}x" + 10.times { + puts Benchmark.measure { + ITER.times { Posix.time(nil) } + } } -} -puts "Benchmark FFI time(3) with pre-allocated buffer performance, #{ITER}x" -buf = FFI::Buffer.new(:time_t) -10.times { - puts Benchmark.measure { - ITER.times { Posix.time(buf) } + puts "Benchmark FFI time(3) with pre-allocated buffer performance, #{ITER}x" + buf = FFI::Buffer.new(:time_t) + 10.times { + puts Benchmark.measure { + ITER.times { Posix.time(buf) } + } } -} -puts "Benchmark FFI time(3) with loop-allocated buffer performance, #{ITER}x" -10.times { - puts Benchmark.measure { - ITER.times { Posix.time(FFI::Buffer.new(:time_t)) } + puts "Benchmark FFI time(3) with loop-allocated buffer performance, #{ITER}x" + 10.times { + puts Benchmark.measure { + ITER.times { Posix.time(FFI::Buffer.new(:time_t)) } + } } -} -puts "Benchmark FFI time(3) with pre-allocated pointer performance, #{ITER}x" -buf = FFI::MemoryPointer.new(:time_t) -10.times { - puts Benchmark.measure { - ITER.times { Posix.time(buf) } + puts "Benchmark FFI time(3) with pre-allocated pointer performance, #{ITER}x" + buf = FFI::MemoryPointer.new(:time_t) + 10.times { + puts Benchmark.measure { + ITER.times { Posix.time(buf) } + } } -} -puts "Benchmark Time.now performance, #{ITER}x" -10.times { - puts Benchmark.measure { - ITER.times { Time.now } + puts "Benchmark Time.now performance, #{ITER}x" + 10.times { + puts Benchmark.measure { + ITER.times { Time.now } + } } -} +end diff --git a/bench/bench_umask.rb b/bench/bench_umask.rb index 2ec3fcd6b..3692c35c7 100644 --- a/bench/bench_umask.rb +++ b/bench/bench_umask.rb @@ -1,60 +1,62 @@ require_relative 'bench_helper' -module Posix - extend FFI::Library - ffi_lib 'c' - attach_function 'umask', [ :int ], :int -end -module NativeFile - extend FFI::Library - ffi_lib 'c' - # Attaching the function to this module is about 10% faster than calling Posix.umask - if FFI::Platform.windows? - attach_function :_umask, '_umask', [ :int ], :int - else - attach_function :_umask, 'umask', [ :int ], :int +module BenchUmask + module Posix + extend FFI::Library + ffi_lib 'c' + attach_function 'umask', [ :int ], :int end - def self.umask(mask = nil) - if mask - _umask(mask) + module NativeFile + extend FFI::Library + ffi_lib 'c' + # Attaching the function to this module is about 10% faster than calling Posix.umask + if FFI::Platform.windows? + attach_function :_umask, '_umask', [ :int ], :int else - old = _umask(0) - _umask(old) - old + attach_function :_umask, 'umask', [ :int ], :int + end + def self.umask(mask = nil) + if mask + _umask(mask) + else + old = _umask(0) + _umask(old) + old + end end end -end -puts "FFI umask=#{NativeFile.umask} File.umask=#{File.umask}" -puts "Benchmark File.umask(0777) performance, #{ITER}x" -10.times { - puts Benchmark.measure { - ITER.times { File.umask(0777) } + puts "FFI umask=#{NativeFile.umask} File.umask=#{File.umask}" + puts "Benchmark File.umask(0777) performance, #{ITER}x" + 10.times { + puts Benchmark.measure { + ITER.times { File.umask(0777) } + } } -} -puts "Benchmark FFI File.umask(0777) performance, #{ITER}x" + puts "Benchmark FFI File.umask(0777) performance, #{ITER}x" -10.times { - puts Benchmark.measure { - ITER.times { NativeFile.umask(0777) } + 10.times { + puts Benchmark.measure { + ITER.times { NativeFile.umask(0777) } + } } -} -puts "Benchmark FFI Posix.umask(0777) performance, #{ITER}x" + puts "Benchmark FFI Posix.umask(0777) performance, #{ITER}x" -10.times { - puts Benchmark.measure { - ITER.times { Posix.umask(0777) } + 10.times { + puts Benchmark.measure { + ITER.times { Posix.umask(0777) } + } } -} -puts "Benchmark File.umask() performance, #{ITER}x" -10.times { - puts Benchmark.measure { - ITER.times { File.umask } + puts "Benchmark File.umask() performance, #{ITER}x" + 10.times { + puts Benchmark.measure { + ITER.times { File.umask } + } } -} -puts "Benchmark FFI File.umask() performance, #{ITER}x" + puts "Benchmark FFI File.umask() performance, #{ITER}x" -10.times { - puts Benchmark.measure { - ITER.times { NativeFile.umask } + 10.times { + puts Benchmark.measure { + ITER.times { NativeFile.umask } + } } -} +end diff --git a/lib/ffi/struct.rb b/lib/ffi/struct.rb index 126d437ce..0d59eea6d 100644 --- a/lib/ffi/struct.rb +++ b/lib/ffi/struct.rb @@ -204,7 +204,7 @@ class << self # end # @note Creating a layout from a hash +spec+ is supported only for Ruby 1.9. def layout(*spec) - #raise RuntimeError, "struct layout already defined for #{self.inspect}" if defined?(@layout) + warn "[DEPRECATION] Struct layout is already defined for class #{self.inspect}. Redefinition as in #{caller[0]} will be disallowed in ffi-2.0." if defined?(@layout) return @layout if spec.size == 0 builder = StructLayoutBuilder.new diff --git a/spec/ffi/callback_spec.rb b/spec/ffi/callback_spec.rb index 400364397..b6ddafc48 100644 --- a/spec/ffi/callback_spec.rb +++ b/spec/ffi/callback_spec.rb @@ -5,876 +5,879 @@ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -describe "Callback" do -# module LibC -# extend FFI::Library -# callback :qsort_cmp, [ :pointer, :pointer ], :int -# attach_function :qsort, [ :pointer, :int, :int, :qsort_cmp ], :int -# end -# it "arguments get passed correctly" do -# p = MemoryPointer.new(:int, 2) -# p.put_array_of_int32(0, [ 1 , 2 ]) -# args = [] -# cmp = proc do |p1, p2| args.push(p1.get_int(0)); args.push(p2.get_int(0)); 0; end -# # this is a bit dodgey, as it relies on qsort passing the args in order -# LibC.qsort(p, 2, 4, cmp) -# args.should == [ 1, 2 ] -# end -# -# it "Block can be substituted for Callback as last argument" do -# p = MemoryPointer.new(:int, 2) -# p.put_array_of_int32(0, [ 1 , 2 ]) -# args = [] -# # this is a bit dodgey, as it relies on qsort passing the args in order -# LibC.qsort(p, 2, 4) do |p1, p2| -# args.push(p1.get_int(0)) -# args.push(p2.get_int(0)) -# 0 -# end -# args.should == [ 1, 2 ] -# end - module LibTest - extend FFI::Library - ffi_lib TestLibrary::PATH - class S8F32S32 < FFI::Struct - layout :s8, :char, :f32, :float, :s32, :int - end - - callback :cbVrS8, [ ], :char - callback :cbVrU8, [ ], :uchar - callback :cbVrS16, [ ], :short - callback :cbVrU16, [ ], :ushort - callback :cbVrS32, [ ], :int - callback :cbVrU32, [ ], :uint - callback :cbVrL, [ ], :long - callback :cbVrUL, [ ], :ulong - callback :cbVrS64, [ ], :long_long - callback :cbVrU64, [ ], :ulong_long - callback :cbVrP, [], :pointer - callback :cbVrZ, [], :bool - callback :cbCrV, [ :char ], :void - callback :cbSrV, [ :short ], :void - callback :cbIrV, [ :int ], :void - callback :cbLrV, [ :long ], :void - callback :cbULrV, [ :ulong ], :void - callback :cbLrV, [ :long_long ], :void - callback :cbVrT, [ ], S8F32S32.by_value - callback :cbTrV, [ S8F32S32.by_value ], :void - callback :cbYrV, [ S8F32S32.ptr ], :void - callback :cbVrY, [ ], S8F32S32.ptr - - attach_function :testCallbackVrS8, :testClosureVrB, [ :cbVrS8 ], :char - attach_function :testCallbackVrU8, :testClosureVrB, [ :cbVrU8 ], :uchar - attach_function :testCallbackVrS16, :testClosureVrS, [ :cbVrS16 ], :short - attach_function :testCallbackVrU16, :testClosureVrS, [ :cbVrU16 ], :ushort - attach_function :testCallbackVrS32, :testClosureVrI, [ :cbVrS32 ], :int - attach_function :testCallbackVrU32, :testClosureVrI, [ :cbVrU32 ], :uint - attach_function :testCallbackVrL, :testClosureVrL, [ :cbVrL ], :long - attach_function :testCallbackVrZ, :testClosureVrZ, [ :cbVrZ ], :bool - attach_function :testCallbackVrUL, :testClosureVrL, [ :cbVrUL ], :ulong - attach_function :testCallbackVrS64, :testClosureVrLL, [ :cbVrS64 ], :long_long - attach_function :testCallbackVrU64, :testClosureVrLL, [ :cbVrU64 ], :ulong_long - attach_function :testCallbackVrP, :testClosureVrP, [ :cbVrP ], :pointer - attach_function :testCallbackReturningFunction, :testClosureVrP, [ :cbVrP ], :cbVrP - attach_function :testCallbackVrY, :testClosureVrP, [ :cbVrY ], S8F32S32.ptr - attach_function :testCallbackVrT, :testClosureVrT, [ :cbVrT ], S8F32S32.by_value - attach_function :testCallbackTrV, :testClosureTrV, [ :cbTrV, S8F32S32.ptr ], :void - attach_variable :cbVrS8, :gvar_pointer, :cbVrS8 - attach_variable :pVrS8, :gvar_pointer, :pointer - attach_function :testGVarCallbackVrS8, :testClosureVrB, [ :pointer ], :char - attach_function :testOptionalCallbackCrV, :testOptionalClosureBrV, [ :cbCrV, :char ], :void - - end +module CallbackSpecs + describe "Callback" do + # module LibC + # extend FFI::Library + # callback :qsort_cmp, [ :pointer, :pointer ], :int + # attach_function :qsort, [ :pointer, :int, :int, :qsort_cmp ], :int + # end + # it "arguments get passed correctly" do + # p = MemoryPointer.new(:int, 2) + # p.put_array_of_int32(0, [ 1 , 2 ]) + # args = [] + # cmp = proc do |p1, p2| args.push(p1.get_int(0)); args.push(p2.get_int(0)); 0; end + # # this is a bit dodgey, as it relies on qsort passing the args in order + # LibC.qsort(p, 2, 4, cmp) + # args.should == [ 1, 2 ] + # end + # + # it "Block can be substituted for Callback as last argument" do + # p = MemoryPointer.new(:int, 2) + # p.put_array_of_int32(0, [ 1 , 2 ]) + # args = [] + # # this is a bit dodgey, as it relies on qsort passing the args in order + # LibC.qsort(p, 2, 4) do |p1, p2| + # args.push(p1.get_int(0)) + # args.push(p2.get_int(0)) + # 0 + # end + # args.should == [ 1, 2 ] + # end + module LibTest + extend FFI::Library + ffi_lib TestLibrary::PATH + class S8F32S32 < FFI::Struct + layout :s8, :char, :f32, :float, :s32, :int + end - it "returning :char (0)" do - expect(LibTest.testCallbackVrS8 { 0 }).to eq(0) - end + callback :cbVrS8, [ ], :char + callback :cbVrU8, [ ], :uchar + callback :cbVrS16, [ ], :short + callback :cbVrU16, [ ], :ushort + callback :cbVrS32, [ ], :int + callback :cbVrU32, [ ], :uint + callback :cbVrL, [ ], :long + callback :cbVrUL, [ ], :ulong + callback :cbVrS64, [ ], :long_long + callback :cbVrU64, [ ], :ulong_long + callback :cbVrP, [], :pointer + callback :cbVrZ, [], :bool + callback :cbCrV, [ :char ], :void + callback :cbSrV, [ :short ], :void + callback :cbIrV, [ :int ], :void + callback :cbLrV, [ :long ], :void + callback :cbULrV, [ :ulong ], :void + callback :cbLrV, [ :long_long ], :void + callback :cbVrT, [ ], S8F32S32.by_value + callback :cbTrV, [ S8F32S32.by_value ], :void + callback :cbYrV, [ S8F32S32.ptr ], :void + callback :cbVrY, [ ], S8F32S32.ptr + + attach_function :testCallbackVrS8, :testClosureVrB, [ :cbVrS8 ], :char + attach_function :testCallbackVrU8, :testClosureVrB, [ :cbVrU8 ], :uchar + attach_function :testCallbackVrS16, :testClosureVrS, [ :cbVrS16 ], :short + attach_function :testCallbackVrU16, :testClosureVrS, [ :cbVrU16 ], :ushort + attach_function :testCallbackVrS32, :testClosureVrI, [ :cbVrS32 ], :int + attach_function :testCallbackVrU32, :testClosureVrI, [ :cbVrU32 ], :uint + attach_function :testCallbackVrL, :testClosureVrL, [ :cbVrL ], :long + attach_function :testCallbackVrZ, :testClosureVrZ, [ :cbVrZ ], :bool + attach_function :testCallbackVrUL, :testClosureVrL, [ :cbVrUL ], :ulong + attach_function :testCallbackVrS64, :testClosureVrLL, [ :cbVrS64 ], :long_long + attach_function :testCallbackVrU64, :testClosureVrLL, [ :cbVrU64 ], :ulong_long + attach_function :testCallbackVrP, :testClosureVrP, [ :cbVrP ], :pointer + attach_function :testCallbackReturningFunction, :testClosureVrP, [ :cbVrP ], :cbVrP + attach_function :testCallbackVrY, :testClosureVrP, [ :cbVrY ], S8F32S32.ptr + attach_function :testCallbackVrT, :testClosureVrT, [ :cbVrT ], S8F32S32.by_value + attach_function :testCallbackTrV, :testClosureTrV, [ :cbTrV, S8F32S32.ptr ], :void + attach_variable :cbVrS8, :gvar_pointer, :cbVrS8 + attach_variable :pVrS8, :gvar_pointer, :pointer + attach_function :testGVarCallbackVrS8, :testClosureVrB, [ :pointer ], :char + attach_function :testOptionalCallbackCrV, :testOptionalClosureBrV, [ :cbCrV, :char ], :void - it "returning :char (127)" do - expect(LibTest.testCallbackVrS8 { 127 }).to eq(127) - end + end - it "returning :char (-128)" do - expect(LibTest.testCallbackVrS8 { -128 }).to eq(-128) - end - # test wrap around - it "returning :char (128)" do - expect(LibTest.testCallbackVrS8 { 128 }).to eq(-128) - end + it "returning :char (0)" do + expect(LibTest.testCallbackVrS8 { 0 }).to eq(0) + end - it "returning :char (255)" do - expect(LibTest.testCallbackVrS8 { 0xff }).to eq(-1) - end + it "returning :char (127)" do + expect(LibTest.testCallbackVrS8 { 127 }).to eq(127) + end - it "returning :uchar (0)" do - expect(LibTest.testCallbackVrU8 { 0 }).to eq(0) - end + it "returning :char (-128)" do + expect(LibTest.testCallbackVrS8 { -128 }).to eq(-128) + end + # test wrap around + it "returning :char (128)" do + expect(LibTest.testCallbackVrS8 { 128 }).to eq(-128) + end - it "returning :uchar (0xff)" do - expect(LibTest.testCallbackVrU8 { 0xff }).to eq(0xff) - end + it "returning :char (255)" do + expect(LibTest.testCallbackVrS8 { 0xff }).to eq(-1) + end - it "returning :uchar (-1)" do - expect(LibTest.testCallbackVrU8 { -1 }).to eq(0xff) - end + it "returning :uchar (0)" do + expect(LibTest.testCallbackVrU8 { 0 }).to eq(0) + end - it "returning :uchar (128)" do - expect(LibTest.testCallbackVrU8 { 128 }).to eq(128) - end + it "returning :uchar (0xff)" do + expect(LibTest.testCallbackVrU8 { 0xff }).to eq(0xff) + end - it "returning :uchar (-128)" do - expect(LibTest.testCallbackVrU8 { -128 }).to eq(128) - end + it "returning :uchar (-1)" do + expect(LibTest.testCallbackVrU8 { -1 }).to eq(0xff) + end - it "returning :short (0)" do - expect(LibTest.testCallbackVrS16 { 0 }).to eq(0) - end + it "returning :uchar (128)" do + expect(LibTest.testCallbackVrU8 { 128 }).to eq(128) + end - it "returning :short (0x7fff)" do - expect(LibTest.testCallbackVrS16 { 0x7fff }).to eq(0x7fff) - end - # test wrap around - it "returning :short (0x8000)" do - expect(LibTest.testCallbackVrS16 { 0x8000 }).to eq(-0x8000) - end + it "returning :uchar (-128)" do + expect(LibTest.testCallbackVrU8 { -128 }).to eq(128) + end - it "returning :short (0xffff)" do - expect(LibTest.testCallbackVrS16 { 0xffff }).to eq(-1) - end + it "returning :short (0)" do + expect(LibTest.testCallbackVrS16 { 0 }).to eq(0) + end - it "returning :ushort (0)" do - expect(LibTest.testCallbackVrU16 { 0 }).to eq(0) - end + it "returning :short (0x7fff)" do + expect(LibTest.testCallbackVrS16 { 0x7fff }).to eq(0x7fff) + end + # test wrap around + it "returning :short (0x8000)" do + expect(LibTest.testCallbackVrS16 { 0x8000 }).to eq(-0x8000) + end - it "returning :ushort (0x7fff)" do - expect(LibTest.testCallbackVrU16 { 0x7fff }).to eq(0x7fff) - end + it "returning :short (0xffff)" do + expect(LibTest.testCallbackVrS16 { 0xffff }).to eq(-1) + end - it "returning :ushort (0x8000)" do - expect(LibTest.testCallbackVrU16 { 0x8000 }).to eq(0x8000) - end + it "returning :ushort (0)" do + expect(LibTest.testCallbackVrU16 { 0 }).to eq(0) + end - it "returning :ushort (0xffff)" do - expect(LibTest.testCallbackVrU16 { 0xffff }).to eq(0xffff) - end + it "returning :ushort (0x7fff)" do + expect(LibTest.testCallbackVrU16 { 0x7fff }).to eq(0x7fff) + end - it "returning :ushort (-1)" do - expect(LibTest.testCallbackVrU16 { -1 }).to eq(0xffff) - end + it "returning :ushort (0x8000)" do + expect(LibTest.testCallbackVrU16 { 0x8000 }).to eq(0x8000) + end - it "returning :int (0)" do - expect(LibTest.testCallbackVrS32 { 0 }).to eq(0) - end + it "returning :ushort (0xffff)" do + expect(LibTest.testCallbackVrU16 { 0xffff }).to eq(0xffff) + end - it "returning :int (0x7fffffff)" do - expect(LibTest.testCallbackVrS32 { 0x7fffffff }).to eq(0x7fffffff) - end - # test wrap around - it "returning :int (-0x80000000)" do - expect(LibTest.testCallbackVrS32 { -0x80000000 }).to eq(-0x80000000) - end + it "returning :ushort (-1)" do + expect(LibTest.testCallbackVrU16 { -1 }).to eq(0xffff) + end - it "returning :int (-1)" do - expect(LibTest.testCallbackVrS32 { -1 }).to eq(-1) - end + it "returning :int (0)" do + expect(LibTest.testCallbackVrS32 { 0 }).to eq(0) + end - it "returning :uint (0)" do - expect(LibTest.testCallbackVrU32 { 0 }).to eq(0) - end + it "returning :int (0x7fffffff)" do + expect(LibTest.testCallbackVrS32 { 0x7fffffff }).to eq(0x7fffffff) + end + # test wrap around + it "returning :int (-0x80000000)" do + expect(LibTest.testCallbackVrS32 { -0x80000000 }).to eq(-0x80000000) + end - it "returning :uint (0x7fffffff)" do - expect(LibTest.testCallbackVrU32 { 0x7fffffff }).to eq(0x7fffffff) - end - # test wrap around - it "returning :uint (0x80000000)" do - expect(LibTest.testCallbackVrU32 { 0x80000000 }).to eq(0x80000000) - end + it "returning :int (-1)" do + expect(LibTest.testCallbackVrS32 { -1 }).to eq(-1) + end - it "returning :uint (0xffffffff)" do - expect(LibTest.testCallbackVrU32 { 0xffffffff }).to eq(0xffffffff) - end + it "returning :uint (0)" do + expect(LibTest.testCallbackVrU32 { 0 }).to eq(0) + end - it "returning :uint (-1)" do - expect(LibTest.testCallbackVrU32 { -1 }).to eq(0xffffffff) - end + it "returning :uint (0x7fffffff)" do + expect(LibTest.testCallbackVrU32 { 0x7fffffff }).to eq(0x7fffffff) + end + # test wrap around + it "returning :uint (0x80000000)" do + expect(LibTest.testCallbackVrU32 { 0x80000000 }).to eq(0x80000000) + end - it "returning :long (0)" do - expect(LibTest.testCallbackVrL { 0 }).to eq(0) - end + it "returning :uint (0xffffffff)" do + expect(LibTest.testCallbackVrU32 { 0xffffffff }).to eq(0xffffffff) + end - it "returning :long (0x7fffffff)" do - expect(LibTest.testCallbackVrL { 0x7fffffff }).to eq(0x7fffffff) - end - # test wrap around - it "returning :long (-0x80000000)" do - expect(LibTest.testCallbackVrL { -0x80000000 }).to eq(-0x80000000) - end + it "returning :uint (-1)" do + expect(LibTest.testCallbackVrU32 { -1 }).to eq(0xffffffff) + end - it "returning :long (-1)" do - expect(LibTest.testCallbackVrL { -1 }).to eq(-1) - end + it "returning :long (0)" do + expect(LibTest.testCallbackVrL { 0 }).to eq(0) + end - it "returning :ulong (0)" do - expect(LibTest.testCallbackVrUL { 0 }).to eq(0) - end + it "returning :long (0x7fffffff)" do + expect(LibTest.testCallbackVrL { 0x7fffffff }).to eq(0x7fffffff) + end + # test wrap around + it "returning :long (-0x80000000)" do + expect(LibTest.testCallbackVrL { -0x80000000 }).to eq(-0x80000000) + end - it "returning :ulong (0x7fffffff)" do - expect(LibTest.testCallbackVrUL { 0x7fffffff }).to eq(0x7fffffff) - end - # test wrap around - it "returning :ulong (0x80000000)" do - expect(LibTest.testCallbackVrUL { 0x80000000 }).to eq(0x80000000) - end + it "returning :long (-1)" do + expect(LibTest.testCallbackVrL { -1 }).to eq(-1) + end - it "returning :ulong (0xffffffff)" do - expect(LibTest.testCallbackVrUL { 0xffffffff }).to eq(0xffffffff) - end + it "returning :ulong (0)" do + expect(LibTest.testCallbackVrUL { 0 }).to eq(0) + end - it "Callback returning :ulong (-1)" do - if FFI::Platform::LONG_SIZE == 32 - expect(LibTest.testCallbackVrUL { -1 }).to eq(0xffffffff) - else - expect(LibTest.testCallbackVrUL { -1 }).to eq(0xffffffffffffffff) + it "returning :ulong (0x7fffffff)" do + expect(LibTest.testCallbackVrUL { 0x7fffffff }).to eq(0x7fffffff) + end + # test wrap around + it "returning :ulong (0x80000000)" do + expect(LibTest.testCallbackVrUL { 0x80000000 }).to eq(0x80000000) end - end - it "returning :long_long (0)" do - expect(LibTest.testCallbackVrS64 { 0 }).to eq(0) - end + it "returning :ulong (0xffffffff)" do + expect(LibTest.testCallbackVrUL { 0xffffffff }).to eq(0xffffffff) + end - it "returning :long_long (0x7fffffffffffffff)" do - expect(LibTest.testCallbackVrS64 { 0x7fffffffffffffff }).to eq(0x7fffffffffffffff) - end - # test wrap around - it "returning :long_long (-0x8000000000000000)" do - expect(LibTest.testCallbackVrS64 { -0x8000000000000000 }).to eq(-0x8000000000000000) - end + it "Callback returning :ulong (-1)" do + if FFI::Platform::LONG_SIZE == 32 + expect(LibTest.testCallbackVrUL { -1 }).to eq(0xffffffff) + else + expect(LibTest.testCallbackVrUL { -1 }).to eq(0xffffffffffffffff) + end + end - it "returning :long_long (-1)" do - expect(LibTest.testCallbackVrS64 { -1 }).to eq(-1) - end + it "returning :long_long (0)" do + expect(LibTest.testCallbackVrS64 { 0 }).to eq(0) + end - it "returning bool" do - expect(LibTest.testCallbackVrZ { true }).to be true - end + it "returning :long_long (0x7fffffffffffffff)" do + expect(LibTest.testCallbackVrS64 { 0x7fffffffffffffff }).to eq(0x7fffffffffffffff) + end + # test wrap around + it "returning :long_long (-0x8000000000000000)" do + expect(LibTest.testCallbackVrS64 { -0x8000000000000000 }).to eq(-0x8000000000000000) + end - it "returning :pointer (nil)" do - expect(LibTest.testCallbackVrP { nil }).to be_null - end + it "returning :long_long (-1)" do + expect(LibTest.testCallbackVrS64 { -1 }).to eq(-1) + end - it "returning :pointer (MemoryPointer)" do - p = FFI::MemoryPointer.new :long - expect(LibTest.testCallbackVrP { p }).to eq(p) - end + it "returning bool" do + expect(LibTest.testCallbackVrZ { true }).to be true + end - it "returning a callback function" do - ret = LibTest.testCallbackReturningFunction { FFI::Pointer.new(42) } - expect(ret).to be_kind_of(FFI::Function) - expect(ret.address).to eq(42) - end + it "returning :pointer (nil)" do + expect(LibTest.testCallbackVrP { nil }).to be_null + end - it "returning struct by value" do - skip "Segfault on 32 bit MINGW" if RUBY_PLATFORM == 'i386-mingw32' - s = LibTest::S8F32S32.new - s[:s8] = 0x12 - s[:s32] = 0x1eefbeef - s[:f32] = 1.234567 - ret = LibTest.testCallbackVrT { s } - expect(ret[:s8]).to eq(s[:s8]) - expect(ret[:f32]).to eq(s[:f32]) - expect(ret[:s32]).to eq(s[:s32]) + it "returning :pointer (MemoryPointer)" do + p = FFI::MemoryPointer.new :long + expect(LibTest.testCallbackVrP { p }).to eq(p) + end - end + it "returning a callback function" do + ret = LibTest.testCallbackReturningFunction { FFI::Pointer.new(42) } + expect(ret).to be_kind_of(FFI::Function) + expect(ret.address).to eq(42) + end - it "struct by value parameter" do - s = LibTest::S8F32S32.new - s[:s8] = 0x12 - s[:s32] = 0x1eefbeef - s[:f32] = 1.234567 - s2 = LibTest::S8F32S32.new + it "returning struct by value" do + skip "Segfault on 32 bit MINGW" if RUBY_PLATFORM == 'i386-mingw32' + s = LibTest::S8F32S32.new + s[:s8] = 0x12 + s[:s32] = 0x1eefbeef + s[:f32] = 1.234567 + ret = LibTest.testCallbackVrT { s } + expect(ret[:s8]).to eq(s[:s8]) + expect(ret[:f32]).to eq(s[:f32]) + expect(ret[:s32]).to eq(s[:s32]) - LibTest.testCallbackTrV(s) do |struct| - s2[:s8] = struct[:s8] - s2[:f32] = struct[:f32] - s2[:s32] = struct[:s32] end - expect(s2[:s8]).to eql 0x12 - expect(s2[:s32]).to eql 0x1eefbeef - expect(s2[:f32]).to be_within(0.0000001).of 1.234567 - end + it "struct by value parameter" do + s = LibTest::S8F32S32.new + s[:s8] = 0x12 + s[:s32] = 0x1eefbeef + s[:f32] = 1.234567 + s2 = LibTest::S8F32S32.new + + LibTest.testCallbackTrV(s) do |struct| + s2[:s8] = struct[:s8] + s2[:f32] = struct[:f32] + s2[:s32] = struct[:s32] + end + + expect(s2[:s8]).to eql 0x12 + expect(s2[:s32]).to eql 0x1eefbeef + expect(s2[:f32]).to be_within(0.0000001).of 1.234567 + end - - it "global variable" do - proc = Proc.new { 0x1e } - LibTest.cbVrS8 = proc - expect(LibTest.testGVarCallbackVrS8(LibTest.pVrS8)).to eq(0x1e) - end - describe "When the callback is considered optional by the underlying library" do - it "should handle receiving 'nil' in place of the closure" do - expect(LibTest.testOptionalCallbackCrV(nil, 13)).to be_nil + it "global variable" do + proc = Proc.new { 0x1e } + LibTest.cbVrS8 = proc + expect(LibTest.testGVarCallbackVrS8(LibTest.pVrS8)).to eq(0x1e) end - end - describe 'when inlined' do - it 'could be anonymous' do - module LibTest - extend FFI::Library - ffi_lib TestLibrary::PATH - attach_function :testAnonymousCallbackVrS8, :testClosureVrB, [ callback([ ], :char) ], :char + describe "When the callback is considered optional by the underlying library" do + it "should handle receiving 'nil' in place of the closure" do + expect(LibTest.testOptionalCallbackCrV(nil, 13)).to be_nil end - expect(LibTest.testAnonymousCallbackVrS8 { 0 }).to eq(0) end - end - - describe "as return value" do - it "should not blow up when a callback is defined that returns a callback" do - expect(module LibTest - extend FFI::Library - ffi_lib TestLibrary::PATH - callback :cb_return_type_1, [ :short ], :short - callback :cb_lookup_1, [ :short ], :cb_return_type_1 - attach_function :testReturnsCallback_1, :testReturnsClosure, [ :cb_lookup_1, :short ], :cb_return_type_1 - end).to be_an_instance_of FFI::Function + describe 'when inlined' do + it 'could be anonymous' do + module LibTest + extend FFI::Library + ffi_lib TestLibrary::PATH + attach_function :testAnonymousCallbackVrS8, :testClosureVrB, [ callback([ ], :char) ], :char + end + expect(LibTest.testAnonymousCallbackVrS8 { 0 }).to eq(0) + end end - it "should return a callback" do - module LibTest - extend FFI::Library - ffi_lib TestLibrary::PATH - callback :cb_return_type, [ :int ], :int - callback :cb_lookup, [ ], :cb_return_type - attach_function :testReturnsCallback, :testReturnsClosure, [ :cb_lookup, :int ], :int - end - - lookup_proc_called = false - return_proc_called = false + describe "as return value" do - return_proc = Proc.new do |a| - return_proc_called = true - a * 2 - end - lookup_proc = Proc.new do - lookup_proc_called = true - return_proc + it "should not blow up when a callback is defined that returns a callback" do + expect(module LibTest + extend FFI::Library + ffi_lib TestLibrary::PATH + callback :cb_return_type_1, [ :short ], :short + callback :cb_lookup_1, [ :short ], :cb_return_type_1 + attach_function :testReturnsCallback_1, :testReturnsClosure, [ :cb_lookup_1, :short ], :cb_return_type_1 + end).to be_an_instance_of FFI::Function end - val = LibTest.testReturnsCallback(lookup_proc, 0x1234) - expect(val).to eq(0x1234 * 2) - expect(lookup_proc_called).to be true - expect(return_proc_called).to be true - end + it "should return a callback" do + module LibTest + extend FFI::Library + ffi_lib TestLibrary::PATH + callback :cb_return_type, [ :int ], :int + callback :cb_lookup, [ ], :cb_return_type + attach_function :testReturnsCallback, :testReturnsClosure, [ :cb_lookup, :int ], :int + end - it "should return a method callback" do - module LibTest - extend FFI::Library - ffi_lib TestLibrary::PATH - callback :cb_return_type, [ :int ], :int - callback :cb_lookup, [ ], :cb_return_type - attach_function :testReturnsCallback_2, :testReturnsClosure, [ :cb_lookup, :int ], :int - end - module MethodCallback - def self.lookup - method(:perform) + lookup_proc_called = false + return_proc_called = false + + return_proc = Proc.new do |a| + return_proc_called = true + a * 2 end - def self.perform num - num * 2 + lookup_proc = Proc.new do + lookup_proc_called = true + return_proc end + + val = LibTest.testReturnsCallback(lookup_proc, 0x1234) + expect(val).to eq(0x1234 * 2) + expect(lookup_proc_called).to be true + expect(return_proc_called).to be true end - expect(LibTest.testReturnsCallback_2(MethodCallback.method(:lookup), 0x1234)).to eq(0x2468) - end + it "should return a method callback" do + module LibTest + extend FFI::Library + ffi_lib TestLibrary::PATH + callback :cb_return_type, [ :int ], :int + callback :cb_lookup, [ ], :cb_return_type + attach_function :testReturnsCallback_2, :testReturnsClosure, [ :cb_lookup, :int ], :int + end + module MethodCallback + def self.lookup + method(:perform) + end + def self.perform num + num * 2 + end + end - it 'should not blow up when a callback takes a callback as argument' do - expect(module LibTest - extend FFI::Library - ffi_lib TestLibrary::PATH - callback :cb_argument, [ :int ], :int - callback :cb_with_cb_argument, [ :cb_argument, :int ], :int - attach_function :testCallbackAsArgument_2, :testArgumentClosure, [ :cb_with_cb_argument, :int ], :int - end).to be_an_instance_of FFI::Function - end - it 'should be able to use the callback argument' do - module LibTest - extend FFI::Library - ffi_lib TestLibrary::PATH - callback :cb_argument, [ :int ], :int - callback :cb_with_cb_argument, [ :cb_argument, :int ], :int - attach_function :testCallbackAsArgument, :testArgumentClosure, [ :cb_with_cb_argument, :cb_argument, :int ], :int - end - callback_arg_called = false - callback_with_callback_arg_called = false - callback_arg = Proc.new do |val| - callback_arg_called = true - val * 2 + expect(LibTest.testReturnsCallback_2(MethodCallback.method(:lookup), 0x1234)).to eq(0x2468) end - callback_with_callback_arg = Proc.new do |cb, val| - callback_with_callback_arg_called = true - cb.call(val) + + it 'should not blow up when a callback takes a callback as argument' do + expect(module LibTest + extend FFI::Library + ffi_lib TestLibrary::PATH + callback :cb_argument, [ :int ], :int + callback :cb_with_cb_argument, [ :cb_argument, :int ], :int + attach_function :testCallbackAsArgument_2, :testArgumentClosure, [ :cb_with_cb_argument, :int ], :int + end).to be_an_instance_of FFI::Function end - val = LibTest.testCallbackAsArgument(callback_with_callback_arg, callback_arg, 0xff1) - expect(val).to eq(0xff1 * 2) - expect(callback_arg_called).to be true - expect(callback_with_callback_arg_called).to be true - end - it 'function returns callable object' do - module LibTest - extend FFI::Library - ffi_lib TestLibrary::PATH - callback :funcptr, [ :int ], :int - attach_function :testReturnsFunctionPointer, [ ], :funcptr + it 'should be able to use the callback argument' do + module LibTest + extend FFI::Library + ffi_lib TestLibrary::PATH + callback :cb_argument, [ :int ], :int + callback :cb_with_cb_argument, [ :cb_argument, :int ], :int + attach_function :testCallbackAsArgument, :testArgumentClosure, [ :cb_with_cb_argument, :cb_argument, :int ], :int + end + callback_arg_called = false + callback_with_callback_arg_called = false + callback_arg = Proc.new do |val| + callback_arg_called = true + val * 2 + end + callback_with_callback_arg = Proc.new do |cb, val| + callback_with_callback_arg_called = true + cb.call(val) + end + val = LibTest.testCallbackAsArgument(callback_with_callback_arg, callback_arg, 0xff1) + expect(val).to eq(0xff1 * 2) + expect(callback_arg_called).to be true + expect(callback_with_callback_arg_called).to be true + end + it 'function returns callable object' do + module LibTest + extend FFI::Library + ffi_lib TestLibrary::PATH + callback :funcptr, [ :int ], :int + attach_function :testReturnsFunctionPointer, [ ], :funcptr + end + f = LibTest.testReturnsFunctionPointer + expect(f.call(3)).to eq(6) end - f = LibTest.testReturnsFunctionPointer - expect(f.call(3)).to eq(6) end end - end +module CallbackWithSpecs + describe "Callback with " do + # + # Test callbacks that take an argument, returning void + # + module LibTest + extend FFI::Library + ffi_lib TestLibrary::PATH + class S8F32S32 < FFI::Struct + layout :s8, :char, :f32, :float, :s32, :int + end -describe "Callback with " do - # - # Test callbacks that take an argument, returning void - # - module LibTest - extend FFI::Library - ffi_lib TestLibrary::PATH - - class S8F32S32 < FFI::Struct - layout :s8, :char, :f32, :float, :s32, :int - end - - callback :cbS8rV, [ :char ], :void - callback :cbU8rV, [ :uchar ], :void - callback :cbS16rV, [ :short ], :void - callback :cbU16rV, [ :ushort ], :void - - callback :cbZrV, [ :bool ], :void - callback :cbS32rV, [ :int ], :void - callback :cbU32rV, [ :uint ], :void - - callback :cbLrV, [ :long ], :void - callback :cbULrV, [ :ulong ], :void - callback :cbArV, [ :string ], :void - callback :cbPrV, [ :pointer], :void - callback :cbYrV, [ S8F32S32.ptr ], :void - - callback :cbS64rV, [ :long_long ], :void - attach_function :testCallbackCrV, :testClosureBrV, [ :cbS8rV, :char ], :void - attach_function :testCallbackU8rV, :testClosureBrV, [ :cbU8rV, :uchar ], :void - attach_function :testCallbackSrV, :testClosureSrV, [ :cbS16rV, :short ], :void - attach_function :testCallbackU16rV, :testClosureSrV, [ :cbU16rV, :ushort ], :void - attach_function :testCallbackZrV, :testClosureZrV, [ :cbZrV, :bool ], :void - attach_function :testCallbackIrV, :testClosureIrV, [ :cbS32rV, :int ], :void - attach_function :testCallbackU32rV, :testClosureIrV, [ :cbU32rV, :uint ], :void - - attach_function :testCallbackLrV, :testClosureLrV, [ :cbLrV, :long ], :void - attach_function :testCallbackULrV, :testClosureULrV, [ :cbULrV, :ulong ], :void - - attach_function :testCallbackLLrV, :testClosureLLrV, [ :cbS64rV, :long_long ], :void - attach_function :testCallbackArV, :testClosurePrV, [ :cbArV, :string ], :void - attach_function :testCallbackPrV, :testClosurePrV, [ :cbPrV, :pointer], :void - attach_function :testCallbackYrV, :testClosurePrV, [ :cbYrV, S8F32S32.in ], :void - end + callback :cbS8rV, [ :char ], :void + callback :cbU8rV, [ :uchar ], :void + callback :cbS16rV, [ :short ], :void + callback :cbU16rV, [ :ushort ], :void + + callback :cbZrV, [ :bool ], :void + callback :cbS32rV, [ :int ], :void + callback :cbU32rV, [ :uint ], :void + + callback :cbLrV, [ :long ], :void + callback :cbULrV, [ :ulong ], :void + callback :cbArV, [ :string ], :void + callback :cbPrV, [ :pointer], :void + callback :cbYrV, [ S8F32S32.ptr ], :void + + callback :cbS64rV, [ :long_long ], :void + attach_function :testCallbackCrV, :testClosureBrV, [ :cbS8rV, :char ], :void + attach_function :testCallbackU8rV, :testClosureBrV, [ :cbU8rV, :uchar ], :void + attach_function :testCallbackSrV, :testClosureSrV, [ :cbS16rV, :short ], :void + attach_function :testCallbackU16rV, :testClosureSrV, [ :cbU16rV, :ushort ], :void + attach_function :testCallbackZrV, :testClosureZrV, [ :cbZrV, :bool ], :void + attach_function :testCallbackIrV, :testClosureIrV, [ :cbS32rV, :int ], :void + attach_function :testCallbackU32rV, :testClosureIrV, [ :cbU32rV, :uint ], :void + + attach_function :testCallbackLrV, :testClosureLrV, [ :cbLrV, :long ], :void + attach_function :testCallbackULrV, :testClosureULrV, [ :cbULrV, :ulong ], :void + + attach_function :testCallbackLLrV, :testClosureLLrV, [ :cbS64rV, :long_long ], :void + attach_function :testCallbackArV, :testClosurePrV, [ :cbArV, :string ], :void + attach_function :testCallbackPrV, :testClosurePrV, [ :cbPrV, :pointer], :void + attach_function :testCallbackYrV, :testClosurePrV, [ :cbYrV, S8F32S32.in ], :void + end - it "function with Callback plus another arg should raise error if no arg given" do - expect { LibTest.testCallbackCrV { |*a| }}.to raise_error(ArgumentError) - end + it "function with Callback plus another arg should raise error if no arg given" do + expect { LibTest.testCallbackCrV { |*a| }}.to raise_error(ArgumentError) + end - it ":char (0) argument" do - v = 0xdeadbeef - LibTest.testCallbackCrV(0) { |i| v = i } - expect(v).to eq(0) - end + it ":char (0) argument" do + v = 0xdeadbeef + LibTest.testCallbackCrV(0) { |i| v = i } + expect(v).to eq(0) + end - it ":char (127) argument" do - v = 0xdeadbeef - LibTest.testCallbackCrV(127) { |i| v = i } - expect(v).to eq(127) - end + it ":char (127) argument" do + v = 0xdeadbeef + LibTest.testCallbackCrV(127) { |i| v = i } + expect(v).to eq(127) + end - it ":char (-128) argument" do - v = 0xdeadbeef - LibTest.testCallbackCrV(-128) { |i| v = i } - expect(v).to eq(-128) - end + it ":char (-128) argument" do + v = 0xdeadbeef + LibTest.testCallbackCrV(-128) { |i| v = i } + expect(v).to eq(-128) + end - it ":char (-1) argument" do - v = 0xdeadbeef - LibTest.testCallbackCrV(-1) { |i| v = i } - expect(v).to eq(-1) - end + it ":char (-1) argument" do + v = 0xdeadbeef + LibTest.testCallbackCrV(-1) { |i| v = i } + expect(v).to eq(-1) + end - def testCallbackU8rV(value) - v1 = 0xdeadbeef - LibTest.testCallbackU8rV(value) { |i| v1 = i } - expect(v1).to eq(value) + def testCallbackU8rV(value) + v1 = 0xdeadbeef + LibTest.testCallbackU8rV(value) { |i| v1 = i } + expect(v1).to eq(value) - # Using a FFI::Function (v2) should be consistent with the direct callback (v1) - v2 = 0xdeadbeef - fun = FFI::Function.new(:void, [:uchar]) { |i| v2 = i } - LibTest.testCallbackU8rV(fun, value) - expect(v2).to eq(value) - end + # Using a FFI::Function (v2) should be consistent with the direct callback (v1) + v2 = 0xdeadbeef + fun = FFI::Function.new(:void, [:uchar]) { |i| v2 = i } + LibTest.testCallbackU8rV(fun, value) + expect(v2).to eq(value) + end - it ":uchar (0) argument" do - testCallbackU8rV(0) - end + it ":uchar (0) argument" do + testCallbackU8rV(0) + end - it ":uchar (127) argument" do - testCallbackU8rV(127) - end + it ":uchar (127) argument" do + testCallbackU8rV(127) + end - it ":uchar (128) argument" do - testCallbackU8rV(128) - end + it ":uchar (128) argument" do + testCallbackU8rV(128) + end - it ":uchar (255) argument" do - testCallbackU8rV(255) - end + it ":uchar (255) argument" do + testCallbackU8rV(255) + end - it ":short (0) argument" do - v = 0xdeadbeef - LibTest.testCallbackSrV(0) { |i| v = i } - expect(v).to eq(0) - end + it ":short (0) argument" do + v = 0xdeadbeef + LibTest.testCallbackSrV(0) { |i| v = i } + expect(v).to eq(0) + end - it ":short (0x7fff) argument" do - v = 0xdeadbeef - LibTest.testCallbackSrV(0x7fff) { |i| v = i } - expect(v).to eq(0x7fff) - end + it ":short (0x7fff) argument" do + v = 0xdeadbeef + LibTest.testCallbackSrV(0x7fff) { |i| v = i } + expect(v).to eq(0x7fff) + end - it ":short (-0x8000) argument" do - v = 0xdeadbeef - LibTest.testCallbackSrV(-0x8000) { |i| v = i } - expect(v).to eq(-0x8000) - end + it ":short (-0x8000) argument" do + v = 0xdeadbeef + LibTest.testCallbackSrV(-0x8000) { |i| v = i } + expect(v).to eq(-0x8000) + end - it ":short (-1) argument" do - v = 0xdeadbeef - LibTest.testCallbackSrV(-1) { |i| v = i } - expect(v).to eq(-1) - end + it ":short (-1) argument" do + v = 0xdeadbeef + LibTest.testCallbackSrV(-1) { |i| v = i } + expect(v).to eq(-1) + end - it ":ushort (0) argument" do - v = 0xdeadbeef - LibTest.testCallbackU16rV(0) { |i| v = i } - expect(v).to eq(0) - end + it ":ushort (0) argument" do + v = 0xdeadbeef + LibTest.testCallbackU16rV(0) { |i| v = i } + expect(v).to eq(0) + end - it ":ushort (0x7fff) argument" do - v = 0xdeadbeef - LibTest.testCallbackU16rV(0x7fff) { |i| v = i } - expect(v).to eq(0x7fff) - end + it ":ushort (0x7fff) argument" do + v = 0xdeadbeef + LibTest.testCallbackU16rV(0x7fff) { |i| v = i } + expect(v).to eq(0x7fff) + end - it ":ushort (0x8000) argument" do - v = 0xdeadbeef - LibTest.testCallbackU16rV(0x8000) { |i| v = i } - expect(v).to eq(0x8000) - end + it ":ushort (0x8000) argument" do + v = 0xdeadbeef + LibTest.testCallbackU16rV(0x8000) { |i| v = i } + expect(v).to eq(0x8000) + end - it ":ushort (0xffff) argument" do - v = 0xdeadbeef - LibTest.testCallbackU16rV(0xffff) { |i| v = i } - expect(v).to eq(0xffff) - end + it ":ushort (0xffff) argument" do + v = 0xdeadbeef + LibTest.testCallbackU16rV(0xffff) { |i| v = i } + expect(v).to eq(0xffff) + end - it ":bool (true) argument" do - v = false - LibTest.testCallbackZrV(true) { |i| v = i } - expect(v).to be true - end + it ":bool (true) argument" do + v = false + LibTest.testCallbackZrV(true) { |i| v = i } + expect(v).to be true + end - it ":int (0) argument" do - v = 0xdeadbeef - LibTest.testCallbackIrV(0) { |i| v = i } - expect(v).to eq(0) - end + it ":int (0) argument" do + v = 0xdeadbeef + LibTest.testCallbackIrV(0) { |i| v = i } + expect(v).to eq(0) + end - it ":int (0x7fffffff) argument" do - v = 0xdeadbeef - LibTest.testCallbackIrV(0x7fffffff) { |i| v = i } - expect(v).to eq(0x7fffffff) - end + it ":int (0x7fffffff) argument" do + v = 0xdeadbeef + LibTest.testCallbackIrV(0x7fffffff) { |i| v = i } + expect(v).to eq(0x7fffffff) + end - it ":int (-0x80000000) argument" do - v = 0xdeadbeef - LibTest.testCallbackIrV(-0x80000000) { |i| v = i } - expect(v).to eq(-0x80000000) - end + it ":int (-0x80000000) argument" do + v = 0xdeadbeef + LibTest.testCallbackIrV(-0x80000000) { |i| v = i } + expect(v).to eq(-0x80000000) + end - it ":int (-1) argument" do - v = 0xdeadbeef - LibTest.testCallbackIrV(-1) { |i| v = i } - expect(v).to eq(-1) - end + it ":int (-1) argument" do + v = 0xdeadbeef + LibTest.testCallbackIrV(-1) { |i| v = i } + expect(v).to eq(-1) + end - it ":uint (0) argument" do - v = 0xdeadbeef - LibTest.testCallbackU32rV(0) { |i| v = i } - expect(v).to eq(0) - end + it ":uint (0) argument" do + v = 0xdeadbeef + LibTest.testCallbackU32rV(0) { |i| v = i } + expect(v).to eq(0) + end - it ":uint (0x7fffffff) argument" do - v = 0xdeadbeef - LibTest.testCallbackU32rV(0x7fffffff) { |i| v = i } - expect(v).to eq(0x7fffffff) - end + it ":uint (0x7fffffff) argument" do + v = 0xdeadbeef + LibTest.testCallbackU32rV(0x7fffffff) { |i| v = i } + expect(v).to eq(0x7fffffff) + end - it ":uint (0x80000000) argument" do - v = 0xdeadbeef - LibTest.testCallbackU32rV(0x80000000) { |i| v = i } - expect(v).to eq(0x80000000) - end + it ":uint (0x80000000) argument" do + v = 0xdeadbeef + LibTest.testCallbackU32rV(0x80000000) { |i| v = i } + expect(v).to eq(0x80000000) + end - it ":uint (0xffffffff) argument" do - v = 0xdeadbeef - LibTest.testCallbackU32rV(0xffffffff) { |i| v = i } - expect(v).to eq(0xffffffff) - end + it ":uint (0xffffffff) argument" do + v = 0xdeadbeef + LibTest.testCallbackU32rV(0xffffffff) { |i| v = i } + expect(v).to eq(0xffffffff) + end - it ":long (0) argument" do - v = 0xdeadbeef - LibTest.testCallbackLrV(0) { |i| v = i } - expect(v).to eq(0) - end + it ":long (0) argument" do + v = 0xdeadbeef + LibTest.testCallbackLrV(0) { |i| v = i } + expect(v).to eq(0) + end - it ":long (0x7fffffff) argument" do - v = 0xdeadbeef - LibTest.testCallbackLrV(0x7fffffff) { |i| v = i } - expect(v).to eq(0x7fffffff) - end + it ":long (0x7fffffff) argument" do + v = 0xdeadbeef + LibTest.testCallbackLrV(0x7fffffff) { |i| v = i } + expect(v).to eq(0x7fffffff) + end - it ":long (-0x80000000) argument" do - v = 0xdeadbeef - LibTest.testCallbackLrV(-0x80000000) { |i| v = i } - expect(v).to eq(-0x80000000) - end + it ":long (-0x80000000) argument" do + v = 0xdeadbeef + LibTest.testCallbackLrV(-0x80000000) { |i| v = i } + expect(v).to eq(-0x80000000) + end - it ":long (-1) argument" do - v = 0xdeadbeef - LibTest.testCallbackLrV(-1) { |i| v = i } - expect(v).to eq(-1) - end + it ":long (-1) argument" do + v = 0xdeadbeef + LibTest.testCallbackLrV(-1) { |i| v = i } + expect(v).to eq(-1) + end - it ":ulong (0) argument" do - v = 0xdeadbeef - LibTest.testCallbackULrV(0) { |i| v = i } - expect(v).to eq(0) - end + it ":ulong (0) argument" do + v = 0xdeadbeef + LibTest.testCallbackULrV(0) { |i| v = i } + expect(v).to eq(0) + end - it ":ulong (0x7fffffff) argument" do - v = 0xdeadbeef - LibTest.testCallbackULrV(0x7fffffff) { |i| v = i } - expect(v).to eq(0x7fffffff) - end + it ":ulong (0x7fffffff) argument" do + v = 0xdeadbeef + LibTest.testCallbackULrV(0x7fffffff) { |i| v = i } + expect(v).to eq(0x7fffffff) + end - it ":ulong (0x80000000) argument" do - v = 0xdeadbeef - LibTest.testCallbackULrV(0x80000000) { |i| v = i } - expect(v).to eq(0x80000000) - end + it ":ulong (0x80000000) argument" do + v = 0xdeadbeef + LibTest.testCallbackULrV(0x80000000) { |i| v = i } + expect(v).to eq(0x80000000) + end - it ":ulong (0xffffffff) argument" do - v = 0xdeadbeef - LibTest.testCallbackULrV(0xffffffff) { |i| v = i } - expect(v).to eq(0xffffffff) - end + it ":ulong (0xffffffff) argument" do + v = 0xdeadbeef + LibTest.testCallbackULrV(0xffffffff) { |i| v = i } + expect(v).to eq(0xffffffff) + end - it ":long_long (0) argument" do - v = 0xdeadbeef - LibTest.testCallbackLLrV(0) { |i| v = i } - expect(v).to eq(0) - end + it ":long_long (0) argument" do + v = 0xdeadbeef + LibTest.testCallbackLLrV(0) { |i| v = i } + expect(v).to eq(0) + end - it ":long_long (0x7fffffffffffffff) argument" do - v = 0xdeadbeef - LibTest.testCallbackLLrV(0x7fffffffffffffff) { |i| v = i } - expect(v).to eq(0x7fffffffffffffff) - end + it ":long_long (0x7fffffffffffffff) argument" do + v = 0xdeadbeef + LibTest.testCallbackLLrV(0x7fffffffffffffff) { |i| v = i } + expect(v).to eq(0x7fffffffffffffff) + end - it ":long_long (-0x8000000000000000) argument" do - v = 0xdeadbeef - LibTest.testCallbackLLrV(-0x8000000000000000) { |i| v = i } - expect(v).to eq(-0x8000000000000000) - end + it ":long_long (-0x8000000000000000) argument" do + v = 0xdeadbeef + LibTest.testCallbackLLrV(-0x8000000000000000) { |i| v = i } + expect(v).to eq(-0x8000000000000000) + end - it ":long_long (-1) argument" do - v = 0xdeadbeef - LibTest.testCallbackLLrV(-1) { |i| v = i } - expect(v).to eq(-1) - end + it ":long_long (-1) argument" do + v = 0xdeadbeef + LibTest.testCallbackLLrV(-1) { |i| v = i } + expect(v).to eq(-1) + end - it ":string argument" do - v = nil - LibTest.testCallbackArV("Hello, World") { |i| v = i } - expect(v).to eq("Hello, World") - end + it ":string argument" do + v = nil + LibTest.testCallbackArV("Hello, World") { |i| v = i } + expect(v).to eq("Hello, World") + end - it ":string (nil) argument" do - v = "Hello, World" - LibTest.testCallbackArV(nil) { |i| v = i } - expect(v).to be_nil - end + it ":string (nil) argument" do + v = "Hello, World" + LibTest.testCallbackArV(nil) { |i| v = i } + expect(v).to be_nil + end - it ":pointer argument" do - v = nil - magic = FFI::Pointer.new(0xdeadbeef) - LibTest.testCallbackPrV(magic) { |i| v = i } - expect(v).to eq(magic) - end + it ":pointer argument" do + v = nil + magic = FFI::Pointer.new(0xdeadbeef) + LibTest.testCallbackPrV(magic) { |i| v = i } + expect(v).to eq(magic) + end - it ":pointer (nil) argument" do - v = "Hello, World" - LibTest.testCallbackPrV(nil) { |i| v = i } - expect(v).to eq(FFI::Pointer::NULL) - end + it ":pointer (nil) argument" do + v = "Hello, World" + LibTest.testCallbackPrV(nil) { |i| v = i } + expect(v).to eq(FFI::Pointer::NULL) + end - it "struct by reference argument" do - v = nil - magic = LibTest::S8F32S32.new - LibTest.testCallbackYrV(magic) { |i| v = i } - expect(v.class).to eq(magic.class) - expect(v.pointer).to eq(magic.pointer) - end + it "struct by reference argument" do + v = nil + magic = LibTest::S8F32S32.new + LibTest.testCallbackYrV(magic) { |i| v = i } + expect(v.class).to eq(magic.class) + expect(v.pointer).to eq(magic.pointer) + end - it "struct by reference argument with nil value" do - v = LibTest::S8F32S32.new - LibTest.testCallbackYrV(nil) { |i| v = i } - expect(v.is_a?(FFI::Struct)).to be true - expect(v.pointer).to eq(FFI::Pointer::NULL) - end + it "struct by reference argument with nil value" do + v = LibTest::S8F32S32.new + LibTest.testCallbackYrV(nil) { |i| v = i } + expect(v.is_a?(FFI::Struct)).to be true + expect(v.pointer).to eq(FFI::Pointer::NULL) + end + + it "varargs parameters are rejected" do + expect { + Module.new do + extend FFI::Library + ffi_lib TestLibrary::PATH + callback :cbVrL, [ :varargs ], :long + end + }.to raise_error(ArgumentError) + end - it "varargs parameters are rejected" do - expect { - Module.new do + # + # Test stdcall convention with function and callback. + # This is Windows 32-bit only. + # + if FFI::Platform::OS =~ /windows|cygwin/ && FFI::Platform::ARCH == 'i386' + module LibTestStdcall extend FFI::Library ffi_lib TestLibrary::PATH - callback :cbVrL, [ :varargs ], :long - end - }.to raise_error(ArgumentError) - end + ffi_convention :stdcall - # - # Test stdcall convention with function and callback. - # This is Windows 32-bit only. - # - if FFI::Platform::OS =~ /windows|cygwin/ && FFI::Platform::ARCH == 'i386' - module LibTestStdcall - extend FFI::Library - ffi_lib TestLibrary::PATH - ffi_convention :stdcall - - callback :cbStdcall, [ :pointer, :long ], :void - attach_function :testCallbackStdcall, 'testClosureStdcall', [ :pointer, :cbStdcall, :long ], :bool - end + callback :cbStdcall, [ :pointer, :long ], :void + attach_function :testCallbackStdcall, 'testClosureStdcall', [ :pointer, :cbStdcall, :long ], :bool + end - it "stdcall convention" do - v = 0xdeadbeef - po = FFI::MemoryPointer.new :long - pr = proc{|a,i| v = a,i; i } - res = LibTestStdcall.testCallbackStdcall(po, pr, 0x7fffffff) - expect(v).to eq([po, 0x7fffffff]) - expect(res).to be true + it "stdcall convention" do + v = 0xdeadbeef + po = FFI::MemoryPointer.new :long + pr = proc{|a,i| v = a,i; i } + res = LibTestStdcall.testCallbackStdcall(po, pr, 0x7fffffff) + expect(v).to eq([po, 0x7fffffff]) + expect(res).to be true + end end end end -describe "Callback interop" do - require 'fiddle' - require 'fiddle/import' - require 'timeout' +module CallbackInteropSpecs + describe "Callback interop" do + require 'fiddle' + require 'fiddle/import' + require 'timeout' - module LibTestFFI - extend FFI::Library - ffi_lib TestLibrary::PATH - attach_function :testCallbackVrV, :testClosureVrV, [ :pointer ], :void - attach_function :testCallbackVrV_blocking, :testClosureVrV, [ :pointer ], :void, blocking: true - end - - module LibTestFiddle - extend Fiddle::Importer - dlload TestLibrary::PATH - extern 'void testClosureVrV(void *fp)' - end + module LibTestFFI + extend FFI::Library + ffi_lib TestLibrary::PATH + attach_function :testCallbackVrV, :testClosureVrV, [ :pointer ], :void + attach_function :testCallbackVrV_blocking, :testClosureVrV, [ :pointer ], :void, blocking: true + end - def assert_callback_in_same_thread_called_once - called = 0 - thread = nil - yield proc { - called += 1 - thread = Thread.current - } - expect(called).to eq(1) - expect(thread).to eq(Thread.current) - end + module LibTestFiddle + extend Fiddle::Importer + dlload TestLibrary::PATH + extern 'void testClosureVrV(void *fp)' + end - it "from ffi to ffi" do - assert_callback_in_same_thread_called_once do |block| - func = FFI::Function.new(:void, [:pointer], &block) - LibTestFFI.testCallbackVrV(FFI::Pointer.new(func.to_i)) + def assert_callback_in_same_thread_called_once + called = 0 + thread = nil + yield proc { + called += 1 + thread = Thread.current + } + expect(called).to eq(1) + expect(thread).to eq(Thread.current) end - end - it "from ffi to ffi with blocking:true" do - assert_callback_in_same_thread_called_once do |block| - func = FFI::Function.new(:void, [:pointer], &block) - LibTestFFI.testCallbackVrV_blocking(FFI::Pointer.new(func.to_i)) + it "from ffi to ffi" do + assert_callback_in_same_thread_called_once do |block| + func = FFI::Function.new(:void, [:pointer], &block) + LibTestFFI.testCallbackVrV(FFI::Pointer.new(func.to_i)) + end end - end - # https://github.com/ffi/ffi/issues/527 - if RUBY_VERSION.split('.').map(&:to_i).pack("C*") >= [2,3,0].pack("C*") || RUBY_PLATFORM =~ /java/ - it "from fiddle to ffi" do + it "from ffi to ffi with blocking:true" do assert_callback_in_same_thread_called_once do |block| func = FFI::Function.new(:void, [:pointer], &block) - LibTestFiddle.testClosureVrV(Fiddle::Pointer[func.to_i]) + LibTestFFI.testCallbackVrV_blocking(FFI::Pointer.new(func.to_i)) end end - end - it "from ffi to fiddle" do - assert_callback_in_same_thread_called_once do |block| - func = LibTestFiddle.bind_function(:cbVrV, Fiddle::TYPE_VOID, [], &block) - LibTestFFI.testCallbackVrV(FFI::Pointer.new(func.to_i)) + # https://github.com/ffi/ffi/issues/527 + if RUBY_VERSION.split('.').map(&:to_i).pack("C*") >= [2,3,0].pack("C*") || RUBY_PLATFORM =~ /java/ + it "from fiddle to ffi" do + assert_callback_in_same_thread_called_once do |block| + func = FFI::Function.new(:void, [:pointer], &block) + LibTestFiddle.testClosureVrV(Fiddle::Pointer[func.to_i]) + end + end end - end - it "from ffi to fiddle with blocking:true" do - assert_callback_in_same_thread_called_once do |block| - func = LibTestFiddle.bind_function(:cbVrV, Fiddle::TYPE_VOID, [], &block) - LibTestFFI.testCallbackVrV_blocking(FFI::Pointer.new(func.to_i)) + it "from ffi to fiddle" do + assert_callback_in_same_thread_called_once do |block| + func = LibTestFiddle.bind_function(:cbVrV, Fiddle::TYPE_VOID, [], &block) + LibTestFFI.testCallbackVrV(FFI::Pointer.new(func.to_i)) + end end - end - it "from fiddle to fiddle" do - assert_callback_in_same_thread_called_once do |block| - func = LibTestFiddle.bind_function(:cbVrV, Fiddle::TYPE_VOID, [], &block) - LibTestFiddle.testClosureVrV(Fiddle::Pointer[func.to_i]) + it "from ffi to fiddle with blocking:true" do + assert_callback_in_same_thread_called_once do |block| + func = LibTestFiddle.bind_function(:cbVrV, Fiddle::TYPE_VOID, [], &block) + LibTestFFI.testCallbackVrV_blocking(FFI::Pointer.new(func.to_i)) + end end - end - # https://github.com/ffi/ffi/issues/527 - if RUBY_ENGINE == 'ruby' && RUBY_VERSION.split('.').map(&:to_i).pack("C*") >= [2,3,0].pack("C*") - it "C outside ffi call stack does not deadlock [#527]" do - path = File.join(File.dirname(__FILE__), "embed-test/embed-test.rb") - pid = spawn(RbConfig.ruby, "-Ilib", path, { [:out, :err] => "embed-test.log" }) - begin - Timeout.timeout(10){ Process.wait(pid) } - rescue Timeout::Error - Process.kill(9, pid) - raise - else - if $?.exitstatus != 0 - raise "external process failed:\n#{ File.read("embed-test.log") }" - end + it "from fiddle to fiddle" do + assert_callback_in_same_thread_called_once do |block| + func = LibTestFiddle.bind_function(:cbVrV, Fiddle::TYPE_VOID, [], &block) + LibTestFiddle.testClosureVrV(Fiddle::Pointer[func.to_i]) end + end + + # https://github.com/ffi/ffi/issues/527 + if RUBY_ENGINE == 'ruby' && RUBY_VERSION.split('.').map(&:to_i).pack("C*") >= [2,3,0].pack("C*") + it "C outside ffi call stack does not deadlock [#527]" do + path = File.join(File.dirname(__FILE__), "embed-test/embed-test.rb") + pid = spawn(RbConfig.ruby, "-Ilib", path, { [:out, :err] => "embed-test.log" }) + begin + Timeout.timeout(10){ Process.wait(pid) } + rescue Timeout::Error + Process.kill(9, pid) + raise + else + if $?.exitstatus != 0 + raise "external process failed:\n#{ File.read("embed-test.log") }" + end + end - expect(File.read("embed-test.log")).to match(/callback called with \["hello", 5, 0\]/) + expect(File.read("embed-test.log")).to match(/callback called with \["hello", 5, 0\]/) + end end end end diff --git a/spec/ffi/library_spec.rb b/spec/ffi/library_spec.rb index 0863904b5..ff18f9b71 100644 --- a/spec/ffi/library_spec.rb +++ b/spec/ffi/library_spec.rb @@ -73,7 +73,7 @@ class StructUCDP < FFI::Struct end }.to raise_error(LoadError) end - + end unless RbConfig::CONFIG['target_os'] =~ /mswin|mingw/ @@ -259,12 +259,12 @@ def gvar_test(name, type, val) expect(lib.get).to eq(val) end + class GlobalStruct < FFI::Struct + layout :data, :long + end + [ 0, 0x7fffffff, -0x80000000, -1 ].each do |i| it "structure" do - class GlobalStruct < FFI::Struct - layout :data, :long - end - lib = Module.new do |m| m.extend FFI::Library ffi_lib TestLibrary::PATH diff --git a/spec/ffi/rbx/attach_function_spec.rb b/spec/ffi/rbx/attach_function_spec.rb index 7593662db..eda640fbe 100644 --- a/spec/ffi/rbx/attach_function_spec.rb +++ b/spec/ffi/rbx/attach_function_spec.rb @@ -5,30 +5,32 @@ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -unless FFI::Platform.windows? - class Timeval < FFI::Struct - layout :tv_sec, :ulong, 0, :tv_usec, :ulong, 4 - end +module RbxAttachFunctionSpecs + unless FFI::Platform.windows? + class Timeval < FFI::Struct + layout :tv_sec, :ulong, 0, :tv_usec, :ulong, 4 + end - module LibC - extend FFI::Library - ffi_lib FFI::Library::LIBC + module LibC + extend FFI::Library + ffi_lib FFI::Library::LIBC - attach_function :gettimeofday, [:pointer, :pointer], :int - end - - describe FFI::Library, "#attach_function" do - it "correctly returns a value for gettimeofday" do - t = Timeval.new - time = LibC.gettimeofday(t.pointer, nil) - expect(time).to be_kind_of(Integer) + attach_function :gettimeofday, [:pointer, :pointer], :int end - it "correctly populates a struct for gettimeofday" do - t = Timeval.new - LibC.gettimeofday(t.pointer, nil) - expect(t[:tv_sec]).to be_kind_of(Numeric) - expect(t[:tv_usec]).to be_kind_of(Numeric) + describe FFI::Library, "#attach_function" do + it "correctly returns a value for gettimeofday" do + t = Timeval.new + time = LibC.gettimeofday(t.pointer, nil) + expect(time).to be_kind_of(Integer) + end + + it "correctly populates a struct for gettimeofday" do + t = Timeval.new + LibC.gettimeofday(t.pointer, nil) + expect(t[:tv_sec]).to be_kind_of(Numeric) + expect(t[:tv_usec]).to be_kind_of(Numeric) + end end end end diff --git a/spec/ffi/rbx/struct_spec.rb b/spec/ffi/rbx/struct_spec.rb index a7ed85b44..c2a51fa48 100644 --- a/spec/ffi/rbx/struct_spec.rb +++ b/spec/ffi/rbx/struct_spec.rb @@ -5,14 +5,16 @@ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) -class Timeval < FFI::Struct - layout :tv_sec, :ulong, 0, :tv_usec, :ulong, 4 -end +module RbxStructSpecs + class Timeval < FFI::Struct + layout :tv_sec, :ulong, 0, :tv_usec, :ulong, 4 + end -describe FFI::Struct do - it "allows setting fields" do - t = Timeval.new - t[:tv_sec] = 12 - expect(t[:tv_sec]).to eq(12) + describe FFI::Struct do + it "allows setting fields" do + t = Timeval.new + t[:tv_sec] = 12 + expect(t[:tv_sec]).to eq(12) + end end end diff --git a/spec/ffi/struct_spec.rb b/spec/ffi/struct_spec.rb index cbcdb0936..45e10ec88 100644 --- a/spec/ffi/struct_spec.rb +++ b/spec/ffi/struct_spec.rb @@ -5,6 +5,7 @@ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper")) +module StructSpecs describe "Struct aligns fields correctly" do it "char, followed by an int" do class CIStruct < FFI::Struct @@ -35,430 +36,463 @@ class LLIStruct < FFI::Struct end end -describe "Struct tests" do - StructTypes = { - 's8' => :char, - 's16' => :short, - 's32' => :int, - 's64' => :long_long, - 'long' => :long, - 'f32' => :float, - 'f64' => :double - } - module LibTest - extend FFI::Library - ffi_lib TestLibrary::PATH - attach_function :ptr_ret_pointer, [ :pointer, :int], :string - begin - attach_function :ptr_ret_int32_t, [ :pointer, :int ], :int - rescue FFI::NotFoundError - # NetBSD uses #define instead of typedef for these - attach_function :ptr_ret_int32_t, :ptr_ret___int32_t, [ :pointer, :int ], :int - end - attach_function :ptr_from_address, [ :ulong ], :pointer - attach_function :string_equals, [ :string, :string ], :int - [ 's8', 's16', 's32', 's64', 'f32', 'f64', 'long' ].each do |t| - attach_function "struct_align_#{t}", [ :pointer ], StructTypes[t] - end - end - class PointerMember < FFI::Struct - layout :pointer, :pointer - end - class StringMember < FFI::Struct - layout :string, :string - end - - it "Struct#[:pointer]" do - magic = 0x12345678 - mp = FFI::MemoryPointer.new :long - mp.put_long(0, magic) - smp = FFI::MemoryPointer.new :pointer - smp.put_pointer(0, mp) - s = PointerMember.new smp - expect(s[:pointer]).to eq(mp) - end - - it "Struct#[:pointer].nil? for NULL value" do - magic = 0x12345678 - mp = FFI::MemoryPointer.new :long - mp.put_long(0, magic) - smp = FFI::MemoryPointer.new :pointer - smp.put_pointer(0, nil) - s = PointerMember.new smp - expect(s[:pointer].null?).to be true - end - - it "Struct#[:pointer]=" do - magic = 0x12345678 - mp = FFI::MemoryPointer.new :long - mp.put_long(0, magic) - smp = FFI::MemoryPointer.new :pointer - s = PointerMember.new smp - s[:pointer] = mp - expect(smp.get_pointer(0)).to eq(mp) - end - - it "Struct#[:pointer]=struct" do - smp = FFI::MemoryPointer.new :pointer - s = PointerMember.new smp - expect { s[:pointer] = s }.not_to raise_error Exception - expect { s[:pointer].nil? }.not_to raise_error Exception - end - - it "Struct#[:pointer]=nil" do - smp = FFI::MemoryPointer.new :pointer - s = PointerMember.new smp - s[:pointer] = nil - expect(smp.get_pointer(0)).to be_null - end - - it "Struct#[:string]" do - magic = "test" - mp = FFI::MemoryPointer.new 1024 - mp.put_string(0, magic) - smp = FFI::MemoryPointer.new :pointer - smp.put_pointer(0, mp) - s = StringMember.new smp - expect(s[:string]).to eq(magic) - end - - it "Struct#[:string].nil? for NULL value" do - smp = FFI::MemoryPointer.new :pointer - smp.put_pointer(0, nil) - s = StringMember.new smp - expect(s[:string]).to be_nil - end - - it "Struct#layout works with :name, :type pairs" do - class PairLayout < FFI::Struct - layout :a, :int, :b, :long_long - end - ll_off = (FFI::TYPE_UINT64.alignment == 4 ? 4 : 8) - expect(PairLayout.size).to eq((ll_off + 8)) - mp = FFI::MemoryPointer.new(PairLayout.size) - s = PairLayout.new mp - s[:a] = 0x12345678 - expect(mp.get_int(0)).to eq(0x12345678) - s[:b] = 0xfee1deadbeef - expect(mp.get_int64(ll_off)).to eq(0xfee1deadbeef) - end - - it "Struct#layout works with :name, :type, offset tuples" do - class PairLayout < FFI::Struct - layout :a, :int, 0, :b, :long_long, 4 - end - expect(PairLayout.size).to eq((FFI::TYPE_UINT64.alignment == 4 ? 12 : 16)) - mp = FFI::MemoryPointer.new(PairLayout.size) - s = PairLayout.new mp - s[:a] = 0x12345678 - expect(mp.get_int(0)).to eq(0x12345678) - s[:b] = 0xfee1deadbeef - expect(mp.get_int64(4)).to eq(0xfee1deadbeef) - end - - it "Struct#layout works with mixed :name,:type and :name,:type,offset" do - class MixedLayout < FFI::Struct - layout :a, :int, :b, :long_long, 4 +module StructSpecsStructTests + describe "Struct tests" do + StructTypes = { + 's8' => :char, + 's16' => :short, + 's32' => :int, + 's64' => :long_long, + 'long' => :long, + 'f32' => :float, + 'f64' => :double + } + module LibTest + extend FFI::Library + ffi_lib TestLibrary::PATH + attach_function :ptr_ret_pointer, [ :pointer, :int], :string + begin + attach_function :ptr_ret_int32_t, [ :pointer, :int ], :int + rescue FFI::NotFoundError + # NetBSD uses #define instead of typedef for these + attach_function :ptr_ret_int32_t, :ptr_ret___int32_t, [ :pointer, :int ], :int + end + attach_function :ptr_from_address, [ :ulong ], :pointer + attach_function :string_equals, [ :string, :string ], :int + [ 's8', 's16', 's32', 's64', 'f32', 'f64', 'long' ].each do |t| + attach_function "struct_align_#{t}", [ :pointer ], StructTypes[t] + end + end + class PointerMember < FFI::Struct + layout :pointer, :pointer + end + class StringMember < FFI::Struct + layout :string, :string end - expect(MixedLayout.size).to eq((FFI::TYPE_UINT64.alignment == 4 ? 12 : 16)) - mp = FFI::MemoryPointer.new(MixedLayout.size) - s = MixedLayout.new mp - s[:a] = 0x12345678 - expect(mp.get_int(0)).to eq(0x12345678) - s[:b] = 0xfee1deadbeef - expect(mp.get_int64(4)).to eq(0xfee1deadbeef) - end - - rb_maj, rb_min = RUBY_VERSION.split('.') - if rb_maj.to_i >= 1 && rb_min.to_i >= 9 || RUBY_PLATFORM =~ /java/ - it "Struct#layout withs with a hash of :name => type" do - class HashLayout < FFI::Struct - layout :a => :int, :b => :long_long + + it "Struct#[:pointer]" do + magic = 0x12345678 + mp = FFI::MemoryPointer.new :long + mp.put_long(0, magic) + smp = FFI::MemoryPointer.new :pointer + smp.put_pointer(0, mp) + s = PointerMember.new smp + expect(s[:pointer]).to eq(mp) + end + + it "Struct#[:pointer].nil? for NULL value" do + magic = 0x12345678 + mp = FFI::MemoryPointer.new :long + mp.put_long(0, magic) + smp = FFI::MemoryPointer.new :pointer + smp.put_pointer(0, nil) + s = PointerMember.new smp + expect(s[:pointer].null?).to be true + end + + it "Struct#[:pointer]=" do + magic = 0x12345678 + mp = FFI::MemoryPointer.new :long + mp.put_long(0, magic) + smp = FFI::MemoryPointer.new :pointer + s = PointerMember.new smp + s[:pointer] = mp + expect(smp.get_pointer(0)).to eq(mp) + end + + it "Struct#[:pointer]=struct" do + smp = FFI::MemoryPointer.new :pointer + s = PointerMember.new smp + expect { s[:pointer] = s }.not_to raise_error Exception + expect { s[:pointer].nil? }.not_to raise_error Exception + end + + it "Struct#[:pointer]=nil" do + smp = FFI::MemoryPointer.new :pointer + s = PointerMember.new smp + s[:pointer] = nil + expect(smp.get_pointer(0)).to be_null + end + + it "Struct#[:string]" do + magic = "test" + mp = FFI::MemoryPointer.new 1024 + mp.put_string(0, magic) + smp = FFI::MemoryPointer.new :pointer + smp.put_pointer(0, mp) + s = StringMember.new smp + expect(s[:string]).to eq(magic) + end + + it "Struct#[:string].nil? for NULL value" do + smp = FFI::MemoryPointer.new :pointer + smp.put_pointer(0, nil) + s = StringMember.new smp + expect(s[:string]).to be_nil + end + + it "Struct#layout works with :name, :type pairs" do + s = Class.new(FFI::Struct) do + layout :a, :int, :b, :long_long end ll_off = (FFI::TYPE_UINT64.alignment == 4 ? 4 : 8) - expect(HashLayout.size).to eq(ll_off + 8) - mp = FFI::MemoryPointer.new(HashLayout.size) - s = HashLayout.new mp + expect(s.size).to eq((ll_off + 8)) + mp = FFI::MemoryPointer.new(s.size) + s = s.new mp s[:a] = 0x12345678 expect(mp.get_int(0)).to eq(0x12345678) s[:b] = 0xfee1deadbeef expect(mp.get_int64(ll_off)).to eq(0xfee1deadbeef) end - end - it "subclass overrides initialize without calling super" do - class InitializeWithoutSuper < FFI::Struct - layout :a, :int, :b, :long_long, :d, [:double, 2] - - def initialize(a, b) - self[:a] = a - self[:b] = b - self[:d][0] = 1.2 - self[:d][1] = 3.4 + it "Struct#layout works with :name, :type, offset tuples" do + s = Class.new(FFI::Struct) do + layout :a, :int, 0, :b, :long_long, 4 end - + expect(s.size).to eq((FFI::TYPE_UINT64.alignment == 4 ? 12 : 16)) + mp = FFI::MemoryPointer.new(s.size) + s = s.new mp + s[:a] = 0x12345678 + expect(mp.get_int(0)).to eq(0x12345678) + s[:b] = 0xfee1deadbeef + expect(mp.get_int64(4)).to eq(0xfee1deadbeef) end - s = InitializeWithoutSuper.new(0x1eefbeef, 0xdeadcafebabe) - expect(s[:a]).to eq(0x1eefbeef) - expect(s[:b]).to eq(0xdeadcafebabe) - end - it "Can use Struct subclass as parameter type" do - expect(module StructParam - extend FFI::Library - ffi_lib TestLibrary::PATH - class TestStruct < FFI::Struct - layout :c, :char + it "Struct#layout works with mixed :name,:type and :name,:type,offset" do + class MixedLayout < FFI::Struct + layout :a, :int, :b, :long_long, 4 end - attach_function :struct_field_s8, [ TestStruct.in ], :char - end).to be_an_instance_of FFI::Function - end + expect(MixedLayout.size).to eq((FFI::TYPE_UINT64.alignment == 4 ? 12 : 16)) + mp = FFI::MemoryPointer.new(MixedLayout.size) + s = MixedLayout.new mp + s[:a] = 0x12345678 + expect(mp.get_int(0)).to eq(0x12345678) + s[:b] = 0xfee1deadbeef + expect(mp.get_int64(4)).to eq(0xfee1deadbeef) + end - it "Can use Struct subclass as IN parameter type" do - expect(module StructParam2 - extend FFI::Library - ffi_lib TestLibrary::PATH - class TestStruct < FFI::Struct - layout :c, :char + rb_maj, rb_min = RUBY_VERSION.split('.') + if rb_maj.to_i >= 1 && rb_min.to_i >= 9 || RUBY_PLATFORM =~ /java/ + it "Struct#layout withs with a hash of :name => type" do + class HashLayout < FFI::Struct + layout :a => :int, :b => :long_long + end + ll_off = (FFI::TYPE_UINT64.alignment == 4 ? 4 : 8) + expect(HashLayout.size).to eq(ll_off + 8) + mp = FFI::MemoryPointer.new(HashLayout.size) + s = HashLayout.new mp + s[:a] = 0x12345678 + expect(mp.get_int(0)).to eq(0x12345678) + s[:b] = 0xfee1deadbeef + expect(mp.get_int64(ll_off)).to eq(0xfee1deadbeef) end - attach_function :struct_field_s8, [ TestStruct.in ], :char - end).to be_an_instance_of FFI::Function - end + end + + it "subclass overrides initialize without calling super" do + class InitializeWithoutSuper < FFI::Struct + layout :a, :int, :b, :long_long, :d, [:double, 2] + + def initialize(a, b) + self[:a] = a + self[:b] = b + self[:d][0] = 1.2 + self[:d][1] = 3.4 + end - it "Can use Struct subclass as OUT parameter type" do - expect(module StructParam3 - extend FFI::Library - ffi_lib TestLibrary::PATH - class TestStruct < FFI::Struct - layout :c, :char end - attach_function :struct_field_s8, [ TestStruct.out ], :char - end).to be_an_instance_of FFI::Function - end + s = InitializeWithoutSuper.new(0x1eefbeef, 0xdeadcafebabe) + expect(s[:a]).to eq(0x1eefbeef) + expect(s[:b]).to eq(0xdeadcafebabe) + end - it "can be passed directly as a :pointer parameter" do - class TestStruct < FFI::Struct - layout :i, :int + it "Can use Struct subclass as parameter type" do + expect(module StructParam + extend FFI::Library + ffi_lib TestLibrary::PATH + class TestStruct < FFI::Struct + layout :c, :char + end + attach_function :struct_field_s8, [ TestStruct.in ], :char + end).to be_an_instance_of FFI::Function end - s = TestStruct.new - s[:i] = 0x12 - expect(LibTest.ptr_ret_int32_t(s, 0)).to eq(0x12) - end - it ":char member aligned correctly" do - class AlignChar < FFI::Struct - layout :c, :char, :v, :char + it "Can use Struct subclass as IN parameter type" do + expect(module StructParam2 + extend FFI::Library + ffi_lib TestLibrary::PATH + class TestStruct < FFI::Struct + layout :c, :char + end + attach_function :struct_field_s8, [ TestStruct.in ], :char + end).to be_an_instance_of FFI::Function end - s = AlignChar.new - s[:v] = 0x12 - expect(LibTest.struct_align_s8(s.pointer)).to eq(0x12) - end - it ":short member aligned correctly" do - class AlignShort < FFI::Struct - layout :c, :char, :v, :short + it "Can use Struct subclass as OUT parameter type" do + expect(module StructParam3 + extend FFI::Library + ffi_lib TestLibrary::PATH + class TestStruct < FFI::Struct + layout :c, :char + end + attach_function :struct_field_s8, [ TestStruct.out ], :char + end).to be_an_instance_of FFI::Function end - s = AlignShort.alloc_in - s[:v] = 0x1234 - expect(LibTest.struct_align_s16(s.pointer)).to eq(0x1234) - end - it ":int member aligned correctly" do - class AlignInt < FFI::Struct - layout :c, :char, :v, :int + it "can be passed directly as a :pointer parameter" do + class TestStruct < FFI::Struct + layout :i, :int + end + s = TestStruct.new + s[:i] = 0x12 + expect(LibTest.ptr_ret_int32_t(s, 0)).to eq(0x12) end - s = AlignInt.alloc_in - s[:v] = 0x12345678 - expect(LibTest.struct_align_s32(s.pointer)).to eq(0x12345678) - end - it ":long_long member aligned correctly" do - class AlignLongLong < FFI::Struct - layout :c, :char, :v, :long_long + it ":char member aligned correctly" do + class AlignChar < FFI::Struct + layout :c, :char, :v, :char + end + s = AlignChar.new + s[:v] = 0x12 + expect(LibTest.struct_align_s8(s.pointer)).to eq(0x12) end - s = AlignLongLong.alloc_in - s[:v] = 0x123456789abcdef0 - expect(LibTest.struct_align_s64(s.pointer)).to eq(0x123456789abcdef0) - end - it ":long member aligned correctly" do - class AlignLong < FFI::Struct - layout :c, :char, :v, :long + it ":short member aligned correctly" do + class AlignShort < FFI::Struct + layout :c, :char, :v, :short + end + s = AlignShort.alloc_in + s[:v] = 0x1234 + expect(LibTest.struct_align_s16(s.pointer)).to eq(0x1234) end - s = AlignLong.alloc_in - s[:v] = 0x12345678 - expect(LibTest.struct_align_long(s.pointer)).to eq(0x12345678) - end - it ":float member aligned correctly" do - class AlignFloat < FFI::Struct - layout :c, :char, :v, :float + it ":int member aligned correctly" do + class AlignInt < FFI::Struct + layout :c, :char, :v, :int + end + s = AlignInt.alloc_in + s[:v] = 0x12345678 + expect(LibTest.struct_align_s32(s.pointer)).to eq(0x12345678) end - s = AlignFloat.alloc_in - s[:v] = 1.23456 - expect((LibTest.struct_align_f32(s.pointer) - 1.23456).abs).to be < 0.00001 - end - it ":double member aligned correctly" do - class AlignDouble < FFI::Struct - layout :c, :char, :v, :double + it ":long_long member aligned correctly" do + class AlignLongLong < FFI::Struct + layout :c, :char, :v, :long_long + end + s = AlignLongLong.alloc_in + s[:v] = 0x123456789abcdef0 + expect(LibTest.struct_align_s64(s.pointer)).to eq(0x123456789abcdef0) end - s = AlignDouble.alloc_in - s[:v] = 1.23456789 - expect((LibTest.struct_align_f64(s.pointer) - 1.23456789).abs).to be < 0.00000001 - end - it ":ulong, :pointer struct" do - class ULPStruct < FFI::Struct - layout :ul, :ulong, :p, :pointer + it ":long member aligned correctly" do + class AlignLong < FFI::Struct + layout :c, :char, :v, :long + end + s = AlignLong.alloc_in + s[:v] = 0x12345678 + expect(LibTest.struct_align_long(s.pointer)).to eq(0x12345678) end - s = ULPStruct.alloc_in - s[:ul] = 0xdeadbeef - s[:p] = LibTest.ptr_from_address(0x12345678) - expect(s.pointer.get_ulong(0)).to eq(0xdeadbeef) - end - def test_num_field(type, v) - klass = Class.new(FFI::Struct) - klass.layout :v, type, :dummy, :long - s = klass.new - s[:v] = v - expect(s.pointer.send("get_#{type.to_s}", 0)).to eq(v) - s.pointer.send("put_#{type.to_s}", 0, 0) - expect(s[:v]).to eq(0) - end - def self.int_field_test(type, values) - values.each do |v| - it "#{type} field r/w (#{v.to_s(16)})" do - test_num_field(type, v) + it ":float member aligned correctly" do + class AlignFloat < FFI::Struct + layout :c, :char, :v, :float end + s = AlignFloat.alloc_in + s[:v] = 1.23456 + expect((LibTest.struct_align_f32(s.pointer) - 1.23456).abs).to be < 0.00001 end - end - int_field_test(:char, [ 0, 127, -128, -1 ]) - int_field_test(:uchar, [ 0, 0x7f, 0x80, 0xff ]) - int_field_test(:short, [ 0, 0x7fff, -0x8000, -1 ]) - int_field_test(:ushort, [ 0, 0x7fff, 0x8000, 0xffff ]) - int_field_test(:int, [ 0, 0x7fffffff, -0x80000000, -1 ]) - int_field_test(:uint, [ 0, 0x7fffffff, 0x80000000, 0xffffffff ]) - int_field_test(:long_long, [ 0, 0x7fffffffffffffff, -0x8000000000000000, -1 ]) - int_field_test(:ulong_long, [ 0, 0x7fffffffffffffff, 0x8000000000000000, 0xffffffffffffffff ]) - if FFI::Platform::LONG_SIZE == 32 - int_field_test(:long, [ 0, 0x7fffffff, -0x80000000, -1 ]) - int_field_test(:ulong, [ 0, 0x7fffffff, 0x80000000, 0xffffffff ]) - else - int_field_test(:long, [ 0, 0x7fffffffffffffff, -0x8000000000000000, -1 ]) - int_field_test(:ulong, [ 0, 0x7fffffffffffffff, 0x8000000000000000, 0xffffffffffffffff ]) - end - it ":float field r/w" do - klass = Class.new(FFI::Struct) - klass.layout :v, :float, :dummy, :long + it ":double member aligned correctly" do + class AlignDouble < FFI::Struct + layout :c, :char, :v, :double + end + s = AlignDouble.alloc_in + s[:v] = 1.23456789 + expect((LibTest.struct_align_f64(s.pointer) - 1.23456789).abs).to be < 0.00000001 + end - s = klass.new - value = 1.23456 - s[:v] = value - expect((s.pointer.get_float(0) - value).abs).to be < 0.0001 - end + it ":ulong, :pointer struct" do + class ULPStruct < FFI::Struct + layout :ul, :ulong, :p, :pointer + end + s = ULPStruct.alloc_in + s[:ul] = 0xdeadbeef + s[:p] = LibTest.ptr_from_address(0x12345678) + expect(s.pointer.get_ulong(0)).to eq(0xdeadbeef) + end + def test_num_field(type, v) + klass = Class.new(FFI::Struct) + klass.layout :v, type, :dummy, :long + + s = klass.new + s[:v] = v + expect(s.pointer.send("get_#{type.to_s}", 0)).to eq(v) + s.pointer.send("put_#{type.to_s}", 0, 0) + expect(s[:v]).to eq(0) + end + def self.int_field_test(type, values) + values.each do |v| + it "#{type} field r/w (#{v.to_s(16)})" do + test_num_field(type, v) + end + end + end + int_field_test(:char, [ 0, 127, -128, -1 ]) + int_field_test(:uchar, [ 0, 0x7f, 0x80, 0xff ]) + int_field_test(:short, [ 0, 0x7fff, -0x8000, -1 ]) + int_field_test(:ushort, [ 0, 0x7fff, 0x8000, 0xffff ]) + int_field_test(:int, [ 0, 0x7fffffff, -0x80000000, -1 ]) + int_field_test(:uint, [ 0, 0x7fffffff, 0x80000000, 0xffffffff ]) + int_field_test(:long_long, [ 0, 0x7fffffffffffffff, -0x8000000000000000, -1 ]) + int_field_test(:ulong_long, [ 0, 0x7fffffffffffffff, 0x8000000000000000, 0xffffffffffffffff ]) + if FFI::Platform::LONG_SIZE == 32 + int_field_test(:long, [ 0, 0x7fffffff, -0x80000000, -1 ]) + int_field_test(:ulong, [ 0, 0x7fffffff, 0x80000000, 0xffffffff ]) + else + int_field_test(:long, [ 0, 0x7fffffffffffffff, -0x8000000000000000, -1 ]) + int_field_test(:ulong, [ 0, 0x7fffffffffffffff, 0x8000000000000000, 0xffffffffffffffff ]) + end + + it ":float field r/w" do + klass = Class.new(FFI::Struct) + klass.layout :v, :float, :dummy, :long + + s = klass.new + value = 1.23456 + s[:v] = value + expect((s.pointer.get_float(0) - value).abs).to be < 0.0001 + end + + it ":double field r/w" do + klass = Class.new(FFI::Struct) + klass.layout :v, :double, :dummy, :long + + s = klass.new + value = 1.23456 + s[:v] = value + expect((s.pointer.get_double(0) - value).abs).to be < 0.0001 + end + module EnumFields + extend FFI::Library + TestEnum = enum :test_enum, [:c1, 10, :c2, 20, :c3, 30, :c4, 40] + class TestStruct < FFI::Struct + layout :a, :int, :c, :test_enum, + :d, [ TestEnum, TestEnum.symbols.length ] + end + end - it ":double field r/w" do - klass = Class.new(FFI::Struct) - klass.layout :v, :double, :dummy, :long + it ":enum field r/w" do + s = EnumFields::TestStruct.new + s[:c] = :c3 - s = klass.new - value = 1.23456 - s[:v] = value - expect((s.pointer.get_double(0) - value).abs).to be < 0.0001 - end - module EnumFields - extend FFI::Library - TestEnum = enum :test_enum, [:c1, 10, :c2, 20, :c3, 30, :c4, 40] - class TestStruct < FFI::Struct - layout :a, :int, :c, :test_enum, - :d, [ TestEnum, TestEnum.symbols.length ] + expect(s.pointer.get_uint(FFI::Type::INT32.size)).to eq(30) + expect(s[:c]).to eq(:c3) end - end - it ":enum field r/w" do - s = EnumFields::TestStruct.new - s[:c] = :c3 + it "array of :enum field" do + s = EnumFields::TestStruct.new + EnumFields::TestEnum.symbols.each_with_index do |val, i| + s[:d][i] = val + end - expect(s.pointer.get_uint(FFI::Type::INT32.size)).to eq(30) - expect(s[:c]).to eq(:c3) - end + EnumFields::TestEnum.symbols.each_with_index do |val, i| + expect(s.pointer.get_uint(FFI::Type::INT32.size * (2 + i))).to eq(EnumFields::TestEnum[val]) + end - it "array of :enum field" do - s = EnumFields::TestStruct.new - EnumFields::TestEnum.symbols.each_with_index do |val, i| - s[:d][i] = val + s[:d].each_with_index do |val, i| + expect(val).to eq(EnumFields::TestEnum.symbols[i]) + end end - EnumFields::TestEnum.symbols.each_with_index do |val, i| - expect(s.pointer.get_uint(FFI::Type::INT32.size * (2 + i))).to eq(EnumFields::TestEnum[val]) + module CallbackMember + extend FFI::Library + ffi_lib TestLibrary::PATH + callback :add, [ :int, :int ], :int + callback :sub, [ :int, :int ], :int + class TestStruct < FFI::Struct + layout :add, :add, + :sub, :sub + end + attach_function :struct_call_add_cb, [TestStruct.in, :int, :int], :int + attach_function :struct_call_sub_cb, [TestStruct.in, :int, :int], :int end - s[:d].each_with_index do |val, i| - expect(val).to eq(EnumFields::TestEnum.symbols[i]) + it "Can have CallbackInfo struct field" do + s = CallbackMember::TestStruct.new + add_proc = lambda { |a, b| a+b } + sub_proc = lambda { |a, b| a-b } + s[:add] = add_proc + s[:sub] = sub_proc + expect(CallbackMember.struct_call_add_cb(s, 40, 2)).to eq(42) + expect(CallbackMember.struct_call_sub_cb(s, 44, 2)).to eq(42) end - end - module CallbackMember - extend FFI::Library - ffi_lib TestLibrary::PATH - callback :add, [ :int, :int ], :int - callback :sub, [ :int, :int ], :int - class TestStruct < FFI::Struct - layout :add, :add, - :sub, :sub + it "Can return its members as a list" do + s = Class.new(FFI::Struct) do + layout :a, :int, :b, :int, :c, :int + end + expect(s.members).to include(:a, :b, :c) end - attach_function :struct_call_add_cb, [TestStruct.in, :int, :int], :int - attach_function :struct_call_sub_cb, [TestStruct.in, :int, :int], :int - end - - it "Can have CallbackInfo struct field" do - s = CallbackMember::TestStruct.new - add_proc = lambda { |a, b| a+b } - sub_proc = lambda { |a, b| a-b } - s[:add] = add_proc - s[:sub] = sub_proc - expect(CallbackMember.struct_call_add_cb(s, 40, 2)).to eq(42) - expect(CallbackMember.struct_call_sub_cb(s, 44, 2)).to eq(42) - end - it "Can return its members as a list" do - class TestStruct < FFI::Struct - layout :a, :int, :b, :int, :c, :int + it "Can return its instance members and values as lists" do + s = Class.new(FFI::Struct) do + layout :a, :int, :b, :int, :c, :int + end + s = s.new + expect(s.members).to include(:a, :b, :c) + s[:a] = 1 + s[:b] = 2 + s[:c] = 3 + expect(s.values).to include(1, 2, 3) end - expect(TestStruct.members).to include(:a, :b, :c) - end - it "Can return its instance members and values as lists" do - class TestStruct < FFI::Struct - layout :a, :int, :b, :int, :c, :int + it 'should return an ordered field/offset pairs array' do + s = Class.new(FFI::Struct) do + layout :a, :int, :b, :int, :c, :int + end + s = s.new + expect(s.offsets).to eq([[:a, 0], [:b, 4], [:c, 8]]) + expect(s.offsets).to eq([[:a, 0], [:b, 4], [:c, 8]]) end - s = TestStruct.new - expect(s.members).to include(:a, :b, :c) - s[:a] = 1 - s[:b] = 2 - s[:c] = 3 - expect(s.values).to include(1, 2, 3) - end - it 'should return an ordered field/offset pairs array' do - class TestStruct < FFI::Struct - layout :a, :int, :b, :int, :c, :int + it "Struct#offset_of returns offset of field within struct" do + s = Class.new(FFI::Struct) do + layout :a, :int, :b, :int, :c, :int + end + expect(s.offset_of(:a)).to eq(0) + expect(s.offset_of(:b)).to eq(4) + expect(s.offset_of(:c)).to eq(8) + end + + if FFI::VERSION < "2" + it "warns about redefinition of struct layouts" do + expect do + Class.new(FFI::Struct) do + layout :a, :int + layout :a, :int + end + end.to output(/Redefinition .* will be disallowed in ffi-2.0/).to_stderr + end + else + it "denies redefinition of struct layouts" do + expect do + Class.new(FFI::Struct) do + layout :a, :int + layout :a, :int + end + end.to raise_error(/struct layout already defined/) + end end - s = TestStruct.new - expect(s.offsets).to eq([[:a, 0], [:b, 4], [:c, 8]]) - expect(TestStruct.offsets).to eq([[:a, 0], [:b, 4], [:c, 8]]) - end - it "Struct#offset_of returns offset of field within struct" do - class TestStruct < FFI::Struct - layout :a, :int, :b, :int, :c, :int + it "allows redefinition of struct layouts in derived classes" do + a = Class.new(FFI::Struct) do + layout :a, :char + end + b = Class.new(a) do + layout :a, :char, :b, :char + end + expect(a.members).to eq([:a]) + expect(b.members).to eq([:a, :b]) end - expect(TestStruct.offset_of(:a)).to eq(0) - expect(TestStruct.offset_of(:b)).to eq(4) - expect(TestStruct.offset_of(:c)).to eq(8) end end @@ -793,40 +827,40 @@ class BuggedStruct < FFI::Struct describe "Struct allocation" do it "MemoryPointer.new(Struct, 2)" do - class S < FFI::Struct + s = Class.new(FFI::Struct) do layout :i, :uint end - p = FFI::MemoryPointer.new(S, 2) + p = FFI::MemoryPointer.new(s, 2) expect(p.total).to eq(8) expect(p.type_size).to eq(4) p.put_uint(4, 0xdeadbeef) - expect(S.new(p[1])[:i]).to eq(0xdeadbeef) + expect(s.new(p[1])[:i]).to eq(0xdeadbeef) expect(p[1].address).to eq((p[0].address + 4)) end it "Buffer.new(Struct, 2)" do - class S < FFI::Struct + s = Class.new(FFI::Struct) do layout :i, :uint end - p = FFI::Buffer.new(S, 2) + p = FFI::Buffer.new(s, 2) expect(p.total).to eq(8) expect(p.type_size).to eq(4) p.put_uint(4, 0xdeadbeef) - expect(S.new(p[1])[:i]).to eq(0xdeadbeef) + expect(s.new(p[1])[:i]).to eq(0xdeadbeef) end it "null? should be true when initialized with NULL pointer" do - class S < FFI::Struct + s = Class.new(FFI::Struct) do layout :i, :uint end - expect(S.new(FFI::Pointer::NULL)).to be_null + expect(s.new(FFI::Pointer::NULL)).to be_null end it "null? should be false when initialized with non-NULL pointer" do - class S < FFI::Struct + s = Class.new(FFI::Struct) do layout :i, :uint end - expect(S.new(FFI::MemoryPointer.new(S))).not_to be_null + expect(s.new(FFI::MemoryPointer.new(s))).not_to be_null end it "supports :bool as a struct member" do @@ -880,3 +914,4 @@ class S < FFI::Struct expect { expect(s[:data][1]).to == 0x12345678 }.to raise_error(IndexError) end end +end