ffi 1.9.3 → 1.9.5

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ffi might be problematic. Click here for more details.

Files changed (86) hide show
  1. checksums.yaml +6 -14
  2. data/Rakefile +12 -15
  3. data/ext/ffi_c/DynamicLibrary.c +9 -5
  4. data/ext/ffi_c/DynamicLibrary.h +49 -0
  5. data/ext/ffi_c/Function.c +4 -3
  6. data/ext/ffi_c/FunctionInfo.c +2 -2
  7. data/ext/ffi_c/Platform.c +2 -2
  8. data/ext/ffi_c/Struct.c +1 -0
  9. data/ext/ffi_c/Variadic.c +2 -2
  10. data/ffi.gemspec +5 -5
  11. data/lib/ffi/library.rb +7 -7
  12. data/lib/ffi/platform.rb +4 -1
  13. data/lib/ffi/platform/x86_64-netbsd/types.conf +2 -0
  14. data/lib/ffi/struct.rb +2 -2
  15. data/lib/ffi/version.rb +1 -1
  16. data/libtest/ClosureTest.c +15 -0
  17. data/libtest/FunctionTest.c +12 -0
  18. data/spec/ffi/LICENSE.SPECS +22 -0
  19. data/spec/ffi/async_callback_spec.rb +1 -0
  20. data/spec/ffi/bool_spec.rb +2 -0
  21. data/spec/ffi/buffer_spec.rb +1 -0
  22. data/spec/ffi/callback_spec.rb +31 -4
  23. data/spec/ffi/custom_param_type.rb +1 -0
  24. data/spec/ffi/custom_type_spec.rb +1 -0
  25. data/spec/ffi/dup_spec.rb +1 -1
  26. data/spec/ffi/enum_spec.rb +1 -0
  27. data/spec/ffi/errno_spec.rb +2 -0
  28. data/spec/ffi/ffi_spec.rb +1 -0
  29. data/spec/ffi/fixtures/Benchmark.c +52 -0
  30. data/spec/ffi/fixtures/Benchmark.o +0 -0
  31. data/spec/ffi/fixtures/BoolTest.c +34 -0
  32. data/spec/ffi/fixtures/BoolTest.o +0 -0
  33. data/spec/ffi/fixtures/BufferTest.c +31 -0
  34. data/spec/ffi/fixtures/BufferTest.o +0 -0
  35. data/spec/ffi/fixtures/ClosureTest.c +190 -0
  36. data/spec/ffi/fixtures/ClosureTest.o +0 -0
  37. data/spec/ffi/fixtures/EnumTest.c +34 -0
  38. data/spec/ffi/fixtures/EnumTest.o +0 -0
  39. data/spec/ffi/fixtures/FunctionTest.c +58 -0
  40. data/spec/ffi/fixtures/FunctionTest.o +0 -0
  41. data/spec/ffi/fixtures/GNUmakefile +149 -0
  42. data/spec/ffi/fixtures/GlobalVariable.c +62 -0
  43. data/spec/ffi/fixtures/GlobalVariable.o +0 -0
  44. data/spec/ffi/fixtures/LastErrorTest.c +21 -0
  45. data/spec/ffi/fixtures/LastErrorTest.o +0 -0
  46. data/spec/ffi/fixtures/NumberTest.c +132 -0
  47. data/spec/ffi/fixtures/NumberTest.o +0 -0
  48. data/spec/ffi/fixtures/PointerTest.c +63 -0
  49. data/spec/ffi/fixtures/PointerTest.o +0 -0
  50. data/spec/ffi/fixtures/ReferenceTest.c +23 -0
  51. data/spec/ffi/fixtures/ReferenceTest.o +0 -0
  52. data/spec/ffi/fixtures/StringTest.c +34 -0
  53. data/spec/ffi/fixtures/StringTest.o +0 -0
  54. data/spec/ffi/fixtures/StructTest.c +243 -0
  55. data/spec/ffi/fixtures/StructTest.o +0 -0
  56. data/spec/ffi/fixtures/UnionTest.c +43 -0
  57. data/spec/ffi/fixtures/UnionTest.o +0 -0
  58. data/spec/ffi/fixtures/VariadicTest.c +99 -0
  59. data/spec/ffi/fixtures/VariadicTest.o +0 -0
  60. data/spec/ffi/fixtures/classes.rb +438 -0
  61. data/spec/ffi/function_spec.rb +4 -2
  62. data/spec/ffi/io_spec.rb +17 -0
  63. data/spec/ffi/library_spec.rb +25 -0
  64. data/spec/ffi/long_double.rb +1 -0
  65. data/spec/ffi/managed_struct_spec.rb +1 -1
  66. data/spec/ffi/memorypointer_spec.rb +72 -0
  67. data/spec/ffi/number_spec.rb +2 -0
  68. data/spec/ffi/platform_spec.rb +97 -0
  69. data/spec/ffi/pointer_spec.rb +8 -2
  70. data/spec/ffi/rbx/attach_function_spec.rb +6 -0
  71. data/spec/ffi/rbx/memory_pointer_spec.rb +7 -2
  72. data/spec/ffi/rbx/spec_helper.rb +7 -1
  73. data/spec/ffi/rbx/struct_spec.rb +7 -1
  74. data/spec/ffi/spec_helper.rb +68 -9
  75. data/spec/ffi/string_spec.rb +3 -1
  76. data/spec/ffi/strptr_spec.rb +1 -0
  77. data/spec/ffi/struct_by_ref_spec.rb +4 -3
  78. data/spec/ffi/struct_callback_spec.rb +2 -1
  79. data/spec/ffi/struct_initialize_spec.rb +1 -0
  80. data/spec/ffi/struct_packed_spec.rb +1 -0
  81. data/spec/ffi/struct_spec.rb +99 -39
  82. data/spec/ffi/typedef_spec.rb +15 -3
  83. data/spec/ffi/union_spec.rb +1 -0
  84. data/spec/ffi/variadic_spec.rb +18 -0
  85. data/spec/spec.opts +1 -2
  86. metadata +129 -94
@@ -0,0 +1,17 @@
1
+ #
2
+ # This file is part of ruby-ffi.
3
+ # For licensing, see LICENSE.SPECS
4
+ #
5
+
6
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
7
+ require 'ffi'
8
+
9
+ if false # disabled for #390
10
+ describe "FFI::IO.for_fd" do
11
+ it "produces an IO wrapping the specified file descriptor" do
12
+ expect do
13
+ FFI::IO.for_fd(2, "r")
14
+ end.to_not raise_error
15
+ end
16
+ end
17
+ end
@@ -4,6 +4,8 @@
4
4
  #
5
5
 
6
6
  require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
7
+ require 'ffi'
8
+
7
9
  describe "Library" do
8
10
  describe "#ffi_convention" do
9
11
  it "defaults to :default" do
@@ -24,6 +26,29 @@ describe "Library" do
24
26
  end
25
27
  end
26
28
 
29
+ if FFI::Platform::OS =~ /windows|cygwin/ && FFI::Platform::ARCH == 'i386'
30
+ module LibTestStdcall
31
+ extend FFI::Library
32
+ ffi_lib TestLibrary::PATH
33
+ ffi_convention :stdcall
34
+
35
+ class StructUCDP < FFI::Struct
36
+ layout :a1, :uchar,
37
+ :a2, :double,
38
+ :a3, :pointer
39
+ end
40
+
41
+ attach_function :testStdcallManyParams, [ :pointer, :int8, :int16, :int32, :int64,
42
+ StructUCDP.by_value, StructUCDP.by_ref, :float, :double ], :void
43
+ end
44
+
45
+ it "adds stdcall decoration: testStdcallManyParams@64" do
46
+ s = LibTestStdcall::StructUCDP.new
47
+ po = FFI::MemoryPointer.new :long
48
+ LibTestStdcall.testStdcallManyParams po, 1, 2, 3, 4, s, s, 1.0, 2.0
49
+ end
50
+ end
51
+
27
52
  describe "ffi_lib" do
28
53
  it "empty name list should raise error" do
29
54
  lambda {
@@ -4,6 +4,7 @@
4
4
  #
5
5
 
6
6
  require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
7
+ require 'ffi'
7
8
  require 'bigdecimal'
8
9
 
9
10
  describe ":long_double arguments and return values" do
@@ -4,7 +4,7 @@
4
4
  #
5
5
 
6
6
  require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
7
- require 'java' if RUBY_PLATFORM =~ /java/
7
+ require 'ffi'
8
8
 
9
9
  describe "Managed Struct" do
10
10
  include FFI
@@ -0,0 +1,72 @@
1
+ #
2
+ # This file is part of ruby-ffi.
3
+ # For licensing, see LICENSE.SPECS
4
+ #
5
+
6
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
7
+ require 'ffi'
8
+
9
+ MemoryPointer = FFI::MemoryPointer
10
+
11
+ describe "MemoryPointer#total" do
12
+ it "MemoryPointer.new(:char, 1).total == 1" do
13
+ expect(MemoryPointer.new(:char, 1).total).to eq 1
14
+ end
15
+ it "MemoryPointer.new(:short, 1).total == 2" do
16
+ expect(MemoryPointer.new(:short, 1).total).to eq 2
17
+ end
18
+ it "MemoryPointer.new(:int, 1).total == 4" do
19
+ expect(MemoryPointer.new(:int, 1).total).to eq 4
20
+ end
21
+ it "MemoryPointer.new(:long_long, 1).total == 8" do
22
+ expect(MemoryPointer.new(:long_long, 1).total).to eq 8
23
+ end
24
+ it "MemoryPointer.new(1024).total == 1024" do
25
+ expect(MemoryPointer.new(1024).total).to eq 1024
26
+ end
27
+ end
28
+ describe "MemoryPointer#read_array_of_long" do
29
+ it "foo" do
30
+ ptr = MemoryPointer.new(:long, 1024)
31
+ ptr[0].write_long 1234
32
+ ptr[1].write_long 5678
33
+ l = ptr.read_array_of_long(2)
34
+ expect(l[0]).to eq 1234
35
+ expect(l[1]).to eq 5678
36
+ end
37
+ end
38
+ describe "MemoryPointer argument" do
39
+ module Ptr
40
+ extend FFI::Library
41
+ ffi_lib FFI::Platform::LIBC
42
+ attach_function :memset, [ :pointer, :int, :ulong ], :pointer
43
+ attach_function :memcpy, [ :pointer, :pointer, :ulong ], :pointer
44
+ end
45
+ it "Pointer passed correctly" do
46
+ p = MemoryPointer.new :int, 1
47
+ ret = Ptr.memset(p, 0, p.total)
48
+ expect(ret).to eq p
49
+ end
50
+ it "Data passed to native function" do
51
+ p = MemoryPointer.new :int, 1
52
+ p2 = MemoryPointer.new :int, 1
53
+ p2.put_int(0, 0x5eadbeef)
54
+ Ptr.memcpy(p, p2, p.total)
55
+ expect(p.get_int(0)).to eq p2.get_int(0)
56
+ expect(p2.get_int(0)).not_to eql 0
57
+ end
58
+ end
59
+ describe "MemoryPointer return value" do
60
+ module Stdio
61
+ extend FFI::Library
62
+ ffi_lib FFI::Platform::LIBC
63
+ attach_function :fopen, [ :string, :string ], :pointer
64
+ attach_function :fclose, [ :pointer ], :int
65
+ attach_function :fwrite, [ :pointer, :ulong, :ulong, :string ], :ulong
66
+ end
67
+ it "fopen returns non-nil" do
68
+ fp = Stdio.fopen("/dev/null", "w")
69
+ expect(fp).to_not be_nil
70
+ expect(Stdio.fclose(fp)).to eq 0 unless fp.nil? or fp.null?
71
+ end
72
+ end
@@ -4,6 +4,8 @@
4
4
  #
5
5
 
6
6
  require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
7
+ require 'ffi'
8
+
7
9
  describe "Function with primitive integer arguments" do
8
10
  module LibTest
9
11
  extend FFI::Library
@@ -0,0 +1,97 @@
1
+ #
2
+ # This file is part of ruby-ffi.
3
+ # For licensing, see LICENSE.SPECS
4
+ #
5
+
6
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
7
+ require 'ffi'
8
+
9
+ describe "FFI::Platform::LIBSUFFIX" do
10
+ it "returns 'so'", if: RbConfig::CONFIG['host_os'].match('linux') do
11
+ FFI::Platform::LIBSUFFIX.should == 'so'
12
+ end
13
+
14
+ it "returns 'dll'", if: RbConfig::CONFIG['host_os'].match('windows') do
15
+ FFI::Platform::LIBSUFFIX.should == 'dll'
16
+ end
17
+
18
+ it "returns 'dylib'", if: RbConfig::CONFIG['host_os'].match('darwin') do
19
+ FFI::Platform::LIBSUFFIX.should == 'dylib'
20
+ end
21
+ end
22
+
23
+ describe "FFI::Platform::IS_WINDOWS" do
24
+ it "returns false", if: RbConfig::CONFIG['host_os'].match('linux') do
25
+ FFI::Platform::IS_WINDOWS.should == false
26
+ end
27
+
28
+ it "returns true", if: RbConfig::CONFIG['host_os'].match('windows') do
29
+ FFI::Platform::IS_WINDOWS.should == true
30
+ end
31
+
32
+ it "returns false", if: RbConfig::CONFIG['host_os'].match('darwin') do
33
+ FFI::Platform::IS_WINDOWS.should == false
34
+ end
35
+ end
36
+
37
+ describe "FFI::Platform::ARCH" do
38
+ it "returns the architecture type" do
39
+ FFI::Platform::ARCH.should == RbConfig::CONFIG["target_cpu"]
40
+ end
41
+ end
42
+
43
+ describe "FFI::Platform::OS" do
44
+ it "returns 'linux' as a string", if: RbConfig::CONFIG['host_os'].match('linux') do
45
+ FFI::Platform::OS.should == 'linux'
46
+ end
47
+
48
+ it "returns 'windows' as a string", if: RbConfig::CONFIG['host_os'].match('windows') do
49
+ FFI::Platform::OS.should == 'windows'
50
+ end
51
+
52
+ it "returns 'darwin' as a string", if: RbConfig::CONFIG['host_os'].match('darwin') do
53
+ FFI::Platform::OS.should == 'darwin'
54
+ end
55
+
56
+ describe "FFI::Platform.windows?" do
57
+ it "returns false", if: RbConfig::CONFIG['host_os'].match('linux') do
58
+ FFI::Platform.windows?.should == false
59
+ end
60
+
61
+ it "returns true", if: RbConfig::CONFIG['host_os'].match('windows') do
62
+ FFI::Platform.windows?.should == true
63
+ end
64
+
65
+ it "returns false", if: RbConfig::CONFIG['host_os'].match('darwin') do
66
+ FFI::Platform.windows?.should == false
67
+ end
68
+ end
69
+
70
+ describe "FFI::Platform.mac?" do
71
+ it "returns false", if: RbConfig::CONFIG['host_os'].match('linux') do
72
+ FFI::Platform.mac?.should == false
73
+ end
74
+
75
+ it "returns false", if: RbConfig::CONFIG['host_os'].match('windows') do
76
+ FFI::Platform.mac?.should == false
77
+ end
78
+
79
+ it "returns true", if: RbConfig::CONFIG['host_os'].match('darwin') do
80
+ FFI::Platform.mac?.should == true
81
+ end
82
+ end
83
+
84
+ describe "FFI::Platform.unix?" do
85
+ it "returns true", if: RbConfig::CONFIG['host_os'].match('linux') do
86
+ FFI::Platform.unix?.should == true
87
+ end
88
+
89
+ it "returns false", if: RbConfig::CONFIG['host_os'].match('windows') do
90
+ FFI::Platform.unix?.should == false
91
+ end
92
+
93
+ it "returns true", if: RbConfig::CONFIG['host_os'].match('darwin') do
94
+ FFI::Platform.unix?.should == true
95
+ end
96
+ end
97
+ end
@@ -2,14 +2,20 @@
2
2
  # This file is part of ruby-ffi.
3
3
  # For licensing, see LICENSE.SPECS
4
4
  #
5
+
5
6
  require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
7
+ require 'ffi'
6
8
  require 'delegate'
7
- require 'java' if RUBY_PLATFORM =~ /java/
8
9
 
9
10
  module PointerTestLib
10
11
  extend FFI::Library
11
12
  ffi_lib TestLibrary::PATH
12
- attach_function :ptr_ret_int32_t, [ :pointer, :int ], :int
13
+ begin
14
+ attach_function :ptr_ret_int32_t, [ :pointer, :int ], :int
15
+ rescue FFI::NotFoundError
16
+ # NetBSD uses #define instead of typedef for these
17
+ attach_function :ptr_ret_int32_t, :ptr_ret___int32_t, [ :pointer, :int ], :int
18
+ end
13
19
  attach_function :ptr_from_address, [ FFI::Platform::ADDRESS_SIZE == 32 ? :uint : :ulong_long ], :pointer
14
20
  attach_function :ptr_set_pointer, [ :pointer, :int, :pointer ], :void
15
21
  attach_function :ptr_ret_pointer, [ :pointer, :int ], :pointer
@@ -1,4 +1,10 @@
1
+ #
2
+ # This file is part of ruby-ffi.
3
+ # For licensing, see LICENSE.SPECS
4
+ #
5
+
1
6
  require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
7
+ require 'ffi'
2
8
 
3
9
  class Timeval < FFI::Struct
4
10
  layout :tv_sec, :ulong, 0, :tv_usec, :ulong, 4
@@ -1,6 +1,11 @@
1
1
  # coding: utf-8
2
- require "rubygems"
2
+ #
3
+ # This file is part of ruby-ffi.
4
+ # For licensing, see LICENSE.SPECS
5
+ #
6
+
3
7
  require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
8
+ require 'ffi'
4
9
 
5
10
  module CTest
6
11
  extend FFI::Library
@@ -17,7 +22,7 @@ describe "MemoryPointer" do
17
22
  end
18
23
 
19
24
  it "does not make a pointer from non-strings" do
20
- expect { FFI::MemoryPointer.from_string(nil) }.to raise_error(TypeError)
25
+ expect {FFI::MemoryPointer.from_string(nil)}.to raise_error(TypeError)
21
26
  end
22
27
 
23
28
  it "makes a pointer from a string with multibyte characters" do
@@ -1 +1,7 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper"))
1
+ #
2
+ # This file is part of ruby-ffi.
3
+ # For licensing, see LICENSE.SPECS
4
+ #
5
+
6
+ require File.expand_path(File.join(File.dirname(__FILE__), "../spec_helper"))
7
+ require 'ffi'
@@ -1,4 +1,10 @@
1
+ #
2
+ # This file is part of ruby-ffi.
3
+ # For licensing, see LICENSE.SPECS
4
+ #
5
+
1
6
  require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
7
+ require 'ffi'
2
8
 
3
9
  class Timeval < FFI::Struct
4
10
  layout :tv_sec, :ulong, 0, :tv_usec, :ulong, 4
@@ -10,4 +16,4 @@ describe FFI::Struct do
10
16
  t[:tv_sec] = 12
11
17
  t[:tv_sec].should == 12
12
18
  end
13
- end
19
+ end
@@ -2,21 +2,80 @@
2
2
  # This file is part of ruby-ffi.
3
3
  # For licensing, see LICENSE.SPECS
4
4
  #
5
- require 'rubygems'
5
+
6
6
  require 'rbconfig'
7
+ require 'ffi'
8
+
9
+ CPU = case RbConfig::CONFIG['host_cpu'].downcase
10
+ when /i[3456]86/
11
+ # Darwin always reports i686, even when running in 64bit mode
12
+ if RbConfig::CONFIG['host_os'] =~ /darwin/ && 0xfee1deadbeef.is_a?(Fixnum)
13
+ "x86_64"
14
+ else
15
+ "i386"
16
+ end
17
+
18
+ when /amd64|x86_64/
19
+ "x86_64"
20
+
21
+ when /ppc64|powerpc64/
22
+ "powerpc64"
23
+
24
+ when /ppc|powerpc/
25
+ "powerpc"
26
+
27
+ when /^arm/
28
+ "arm"
29
+
30
+ else
31
+ RbConfig::CONFIG['host_cpu']
32
+ end
33
+
34
+ OS = case RbConfig::CONFIG['host_os'].downcase
35
+ when /linux/
36
+ "linux"
37
+ when /darwin/
38
+ "darwin"
39
+ when /freebsd/
40
+ "freebsd"
41
+ when /openbsd/
42
+ "openbsd"
43
+ when /sunos|solaris/
44
+ "solaris"
45
+ when /mswin|mingw/
46
+ "win32"
47
+ else
48
+ RbConfig::CONFIG['host_os'].downcase
49
+ end
50
+
51
+ def compile_library(path, lib)
52
+
53
+ dir = File.expand_path(path, File.dirname(__FILE__))
54
+ lib = "#{dir}/#{lib}"
55
+ if !File.exists?(lib)
56
+ ldshared = RbConfig::CONFIG["LDSHARED"]
57
+ libs = RbConfig::CONFIG["LIBS"]
58
+ dldflags = RbConfig::CONFIG["DLDFLAGS"]
59
+
60
+ puts Dir.pwd, dir, File.dirname(__FILE__)
61
+
62
+ FileUtils.cd(dir) do
63
+ output = system(*%{#{system('which gmake >/dev/null') && 'gmake' || 'make'} CPU=#{CPU} OS=#{OS} }.tap{|x| puts x.inspect})
64
+ end
7
65
 
8
- if RUBY_PLATFORM =~/java/
9
- libdir = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "lib"))
10
- $:.reject! { |p| p == libdir }
11
- else
12
- $:.unshift File.join(File.dirname(__FILE__), "..", "..", "lib"),
13
- File.join(File.dirname(__FILE__), "..", "..", "build", "#{RbConfig::CONFIG['host_cpu''arch']}", "ffi_c", RUBY_VERSION)
66
+ if $?.exitstatus != 0
67
+ raise "Unable to compile \"#{lib}\""
68
+ end
69
+ end
70
+
71
+ lib
14
72
  end
15
- # puts "loadpath=#{$:.join(':')}"
73
+
16
74
  require "ffi"
17
75
 
18
76
  module TestLibrary
19
- PATH = "build/libtest.#{FFI::Platform::LIBSUFFIX}"
77
+ PATH = compile_library("fixtures", "libtest.#{FFI::Platform::LIBSUFFIX}")
78
+
20
79
  def self.force_gc
21
80
  if RUBY_PLATFORM =~ /java/
22
81
  java.lang.System.gc
@@ -4,6 +4,8 @@
4
4
  #
5
5
 
6
6
  require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
7
+ require 'ffi'
8
+
7
9
  describe "String tests" do
8
10
  include FFI
9
11
  module StrLibTest
@@ -43,7 +45,7 @@ describe "String tests" do
43
45
  end
44
46
  end if false
45
47
  it "casts nil as NULL pointer" do
46
- StrLibTest.string_dummy(nil)
48
+ StrLibTest.string_dummy(nil).should == nil
47
49
  end
48
50
  it "return nil for NULL char*" do
49
51
  StrLibTest.string_null.should == nil