ffi 1.11.1-java → 1.13.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +3 -0
  4. data/.appveyor.yml +30 -0
  5. data/.github/workflows/ci.yml +64 -0
  6. data/.gitignore +25 -0
  7. data/.gitmodules +4 -0
  8. data/.travis.yml +58 -0
  9. data/.yardopts +5 -0
  10. data/CHANGELOG.md +80 -0
  11. data/Gemfile +17 -0
  12. data/LICENSE.SPECS +22 -0
  13. data/README.md +10 -1
  14. data/Rakefile +25 -43
  15. data/ffi.gemspec +43 -0
  16. data/lib/ffi.rb +28 -0
  17. data/lib/ffi/autopointer.rb +203 -0
  18. data/lib/ffi/buffer.rb +4 -0
  19. data/lib/ffi/callback.rb +4 -0
  20. data/lib/ffi/data_converter.rb +67 -0
  21. data/lib/ffi/enum.rb +296 -0
  22. data/lib/ffi/errno.rb +43 -0
  23. data/lib/ffi/ffi.rb +46 -0
  24. data/lib/ffi/io.rb +62 -0
  25. data/lib/ffi/library.rb +592 -0
  26. data/lib/ffi/managedstruct.rb +84 -0
  27. data/lib/ffi/memorypointer.rb +1 -0
  28. data/lib/ffi/platform.rb +175 -0
  29. data/lib/ffi/platform/aarch64-freebsd/types.conf +128 -0
  30. data/lib/ffi/platform/aarch64-freebsd12/types.conf +128 -0
  31. data/lib/ffi/platform/aarch64-linux/types.conf +104 -0
  32. data/lib/ffi/platform/arm-freebsd/types.conf +152 -0
  33. data/lib/ffi/platform/arm-freebsd12/types.conf +152 -0
  34. data/lib/ffi/platform/arm-linux/types.conf +132 -0
  35. data/lib/ffi/platform/i386-cygwin/types.conf +3 -0
  36. data/lib/ffi/platform/i386-darwin/types.conf +100 -0
  37. data/lib/ffi/platform/i386-freebsd/types.conf +152 -0
  38. data/lib/ffi/platform/i386-freebsd12/types.conf +152 -0
  39. data/lib/ffi/platform/i386-gnu/types.conf +107 -0
  40. data/lib/ffi/platform/i386-linux/types.conf +103 -0
  41. data/lib/ffi/platform/i386-netbsd/types.conf +126 -0
  42. data/lib/ffi/platform/i386-openbsd/types.conf +128 -0
  43. data/lib/ffi/platform/i386-solaris/types.conf +122 -0
  44. data/lib/ffi/platform/i386-windows/types.conf +52 -0
  45. data/lib/ffi/platform/ia64-linux/types.conf +104 -0
  46. data/lib/ffi/platform/mips-linux/types.conf +102 -0
  47. data/lib/ffi/platform/mips64-linux/types.conf +104 -0
  48. data/lib/ffi/platform/mips64el-linux/types.conf +104 -0
  49. data/lib/ffi/platform/mipsel-linux/types.conf +102 -0
  50. data/lib/ffi/platform/mipsisa32r6-linux/types.conf +102 -0
  51. data/lib/ffi/platform/mipsisa32r6el-linux/types.conf +102 -0
  52. data/lib/ffi/platform/mipsisa64r6-linux/types.conf +104 -0
  53. data/lib/ffi/platform/mipsisa64r6el-linux/types.conf +104 -0
  54. data/lib/ffi/platform/powerpc-aix/types.conf +180 -0
  55. data/lib/ffi/platform/powerpc-darwin/types.conf +100 -0
  56. data/lib/ffi/platform/powerpc-linux/types.conf +130 -0
  57. data/lib/ffi/platform/powerpc-openbsd/types.conf +156 -0
  58. data/lib/ffi/platform/powerpc64-linux/types.conf +104 -0
  59. data/lib/ffi/platform/s390-linux/types.conf +102 -0
  60. data/lib/ffi/platform/s390x-linux/types.conf +102 -0
  61. data/lib/ffi/platform/sparc-linux/types.conf +102 -0
  62. data/lib/ffi/platform/sparc-solaris/types.conf +128 -0
  63. data/lib/ffi/platform/sparc64-linux/types.conf +102 -0
  64. data/lib/ffi/platform/sparcv9-openbsd/types.conf +156 -0
  65. data/lib/ffi/platform/sparcv9-solaris/types.conf +128 -0
  66. data/lib/ffi/platform/x86_64-cygwin/types.conf +3 -0
  67. data/lib/ffi/platform/x86_64-darwin/types.conf +130 -0
  68. data/lib/ffi/platform/x86_64-dragonflybsd/types.conf +148 -0
  69. data/lib/ffi/platform/x86_64-freebsd/types.conf +128 -0
  70. data/lib/ffi/platform/x86_64-freebsd12/types.conf +158 -0
  71. data/lib/ffi/platform/x86_64-linux/types.conf +132 -0
  72. data/lib/ffi/platform/x86_64-netbsd/types.conf +128 -0
  73. data/lib/ffi/platform/x86_64-openbsd/types.conf +134 -0
  74. data/lib/ffi/platform/x86_64-solaris/types.conf +122 -0
  75. data/lib/ffi/platform/x86_64-windows/types.conf +52 -0
  76. data/lib/ffi/pointer.rb +167 -0
  77. data/lib/ffi/struct.rb +316 -0
  78. data/lib/ffi/struct_by_reference.rb +72 -0
  79. data/lib/ffi/struct_layout.rb +96 -0
  80. data/lib/ffi/struct_layout_builder.rb +227 -0
  81. data/lib/ffi/tools/const_generator.rb +230 -0
  82. data/lib/ffi/tools/generator.rb +105 -0
  83. data/lib/ffi/tools/generator_task.rb +32 -0
  84. data/lib/ffi/tools/struct_generator.rb +194 -0
  85. data/lib/ffi/tools/types_generator.rb +137 -0
  86. data/lib/ffi/types.rb +194 -0
  87. data/lib/ffi/union.rb +43 -0
  88. data/lib/ffi/variadic.rb +78 -0
  89. data/lib/ffi/version.rb +3 -0
  90. data/samples/getlogin.rb +8 -0
  91. data/samples/getpid.rb +8 -0
  92. data/samples/gettimeofday.rb +18 -0
  93. data/samples/hello.rb +8 -0
  94. data/samples/inotify.rb +60 -0
  95. data/samples/pty.rb +75 -0
  96. data/samples/qsort.rb +20 -0
  97. metadata +198 -9
  98. metadata.gz.sig +0 -0
@@ -0,0 +1,105 @@
1
+ require 'ffi/tools/struct_generator'
2
+ require 'ffi/tools/const_generator'
3
+
4
+ module FFI
5
+
6
+ ##
7
+ # Generate files with C structs for FFI::Struct and C constants.
8
+ #
9
+ # == A simple example
10
+ #
11
+ # In file +zlib.rb.ffi+:
12
+ # module Zlib
13
+ # @@@
14
+ # constants do |c|
15
+ # c.include "zlib.h"
16
+ # c.const :ZLIB_VERNUM
17
+ # end
18
+ # @@@
19
+ #
20
+ # class ZStream < FFI::Struct
21
+ #
22
+ # struct do |s|
23
+ # s.name "struct z_stream_s"
24
+ # s.include "zlib.h"
25
+ #
26
+ # s.field :next_in, :pointer
27
+ # s.field :avail_in, :uint
28
+ # s.field :total_in, :ulong
29
+ # end
30
+ # @@@
31
+ # end
32
+ # end
33
+ #
34
+ # Translate the file:
35
+ # require "ffi/tools/generator"
36
+ # FFI::Generator.new "zlib.rb.ffi", "zlib.rb"
37
+ #
38
+ # Generates the file +zlib.rb+ with constant values and offsets:
39
+ # module Zlib
40
+ # ZLIB_VERNUM = 4784
41
+ #
42
+ # class ZStream < FFI::Struct
43
+ # layout :next_in, :pointer, 0,
44
+ # :avail_in, :uint, 8,
45
+ # :total_in, :ulong, 16
46
+ # end
47
+ #
48
+ # @see FFI::Generator::Task for easy integration in a Rakefile
49
+ class Generator
50
+
51
+ def initialize(ffi_name, rb_name, options = {})
52
+ @ffi_name = ffi_name
53
+ @rb_name = rb_name
54
+ @options = options
55
+ @name = File.basename rb_name, '.rb'
56
+
57
+ file = File.read @ffi_name
58
+
59
+ new_file = file.gsub(/^( *)@@@(.*?)@@@/m) do
60
+ @constants = []
61
+ @structs = []
62
+
63
+ indent = $1
64
+ original_lines = $2.count "\n"
65
+
66
+ instance_eval $2, @ffi_name, $`.count("\n")
67
+
68
+ new_lines = []
69
+ @constants.each { |c| new_lines << c.to_ruby }
70
+ @structs.each { |s| new_lines << s.generate_layout }
71
+
72
+ new_lines = new_lines.join("\n").split "\n" # expand multiline blocks
73
+ new_lines = new_lines.map { |line| indent + line }
74
+
75
+ padding = original_lines - new_lines.length
76
+ new_lines += [nil] * padding if padding >= 0
77
+
78
+ new_lines.join "\n"
79
+ end
80
+
81
+ open @rb_name, 'w' do |f|
82
+ f.puts "# This file is generated from `#{@ffi_name}'. Do not edit."
83
+ f.puts
84
+ f.puts new_file
85
+ end
86
+ end
87
+
88
+ def constants(options = {}, &block)
89
+ @constants << FFI::ConstGenerator.new(@name, @options.merge(options), &block)
90
+ end
91
+
92
+ def struct(options = {}, &block)
93
+ @structs << FFI::StructGenerator.new(@name, @options.merge(options), &block)
94
+ end
95
+
96
+ ##
97
+ # Utility converter for constants
98
+
99
+ def to_s
100
+ proc { |obj| obj.to_s.inspect }
101
+ end
102
+
103
+ end
104
+ end
105
+
@@ -0,0 +1,32 @@
1
+ require 'ffi/tools/generator'
2
+ require 'rake'
3
+ require 'rake/tasklib'
4
+
5
+ ##
6
+ # Add Rake tasks that generate files with C structs for FFI::Struct and C constants.
7
+ #
8
+ # @example a simple example for your Rakefile
9
+ # require "ffi/tools/generator_task"
10
+ # # Add a task to generate my_object.rb out of my_object.rb.ffi
11
+ # FFI::Generator::Task.new ["my_object.rb"], cflags: "-I/usr/local/mylibrary"
12
+ #
13
+ # The generated files are also added to the 'clear' task.
14
+ #
15
+ # @see FFI::Generator for a description of the file content
16
+ class FFI::Generator::Task < Rake::TaskLib
17
+
18
+ def initialize(rb_names, options={})
19
+ task :clean do rm_f rb_names end
20
+
21
+ rb_names.each do |rb_name|
22
+ ffi_name = "#{rb_name}.ffi"
23
+
24
+ file rb_name => ffi_name do |t|
25
+ puts "Generating #{rb_name}..." if Rake.application.options.trace
26
+
27
+ FFI::Generator.new ffi_name, rb_name, options
28
+ end
29
+ end
30
+ end
31
+
32
+ end
@@ -0,0 +1,194 @@
1
+ require 'tempfile'
2
+
3
+ module FFI
4
+
5
+ ##
6
+ # Generates an FFI Struct layout.
7
+ #
8
+ # Given the @@@ portion in:
9
+ #
10
+ # class Zlib::ZStream < FFI::Struct
11
+ # @@@
12
+ # name "struct z_stream_s"
13
+ # include "zlib.h"
14
+ #
15
+ # field :next_in, :pointer
16
+ # field :avail_in, :uint
17
+ # field :total_in, :ulong
18
+ #
19
+ # # ...
20
+ # @@@
21
+ # end
22
+ #
23
+ # StructGenerator will create the layout:
24
+ #
25
+ # layout :next_in, :pointer, 0,
26
+ # :avail_in, :uint, 4,
27
+ # :total_in, :ulong, 8,
28
+ # # ...
29
+ #
30
+ # StructGenerator does its best to pad the layout it produces to preserve
31
+ # line numbers. Place the struct definition as close to the top of the file
32
+ # for best results.
33
+
34
+ class StructGenerator
35
+ @options = {}
36
+ attr_accessor :size
37
+ attr_reader :fields
38
+
39
+ def initialize(name, options = {})
40
+ @name = name
41
+ @struct_name = nil
42
+ @includes = []
43
+ @fields = []
44
+ @found = false
45
+ @size = nil
46
+
47
+ if block_given? then
48
+ yield self
49
+ calculate self.class.options.merge(options)
50
+ end
51
+ end
52
+ def self.options=(options)
53
+ @options = options
54
+ end
55
+ def self.options
56
+ @options
57
+ end
58
+ def calculate(options = {})
59
+ binary = File.join Dir.tmpdir, "rb_struct_gen_bin_#{Process.pid}"
60
+
61
+ raise "struct name not set" if @struct_name.nil?
62
+
63
+ Tempfile.open("#{@name}.struct_generator") do |f|
64
+ f.puts "#include <stdio.h>"
65
+
66
+ @includes.each do |inc|
67
+ f.puts "#include <#{inc}>"
68
+ end
69
+
70
+ f.puts "#include <stddef.h>\n\n"
71
+ f.puts "int main(int argc, char **argv)\n{"
72
+ f.puts " #{@struct_name} s;"
73
+ f.puts %[ printf("sizeof(#{@struct_name}) %u\\n", (unsigned int) sizeof(#{@struct_name}));]
74
+
75
+ @fields.each do |field|
76
+ f.puts <<-EOF
77
+ printf("#{field.name} %u %u\\n", (unsigned int) offsetof(#{@struct_name}, #{field.name}),
78
+ (unsigned int) sizeof(s.#{field.name}));
79
+ EOF
80
+ end
81
+
82
+ f.puts "\n return 0;\n}"
83
+ f.flush
84
+
85
+ output = `gcc #{options[:cppflags]} #{options[:cflags]} -D_DARWIN_USE_64_BIT_INODE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -x c -Wall -Werror #{f.path} -o #{binary} 2>&1`
86
+
87
+ unless $?.success? then
88
+ @found = false
89
+ output = output.split("\n").map { |l| "\t#{l}" }.join "\n"
90
+ raise "Compilation error generating struct #{@name} (#{@struct_name}):\n#{output}"
91
+ end
92
+ end
93
+
94
+ output = `#{binary}`.split "\n"
95
+ File.unlink(binary + (FFI::Platform.windows? ? ".exe" : ""))
96
+ sizeof = output.shift
97
+ unless @size
98
+ m = /\s*sizeof\([^)]+\) (\d+)/.match sizeof
99
+ @size = m[1]
100
+ end
101
+
102
+ line_no = 0
103
+ output.each do |line|
104
+ md = line.match(/.+ (\d+) (\d+)/)
105
+ @fields[line_no].offset = md[1].to_i
106
+ @fields[line_no].size = md[2].to_i
107
+
108
+ line_no += 1
109
+ end
110
+
111
+ @found = true
112
+ end
113
+
114
+ def field(name, type=nil)
115
+ field = Field.new(name, type)
116
+ @fields << field
117
+ return field
118
+ end
119
+
120
+ def found?
121
+ @found
122
+ end
123
+
124
+ def dump_config(io)
125
+ io.puts "rbx.platform.#{@name}.sizeof = #{@size}"
126
+
127
+ @fields.each { |field| io.puts field.to_config(@name) }
128
+ end
129
+
130
+ def generate_layout
131
+ buf = ""
132
+
133
+ @fields.each_with_index do |field, i|
134
+ if buf.empty?
135
+ buf << "layout :#{field.name}, :#{field.type}, #{field.offset}"
136
+ else
137
+ buf << " :#{field.name}, :#{field.type}, #{field.offset}"
138
+ end
139
+
140
+ if i < @fields.length - 1
141
+ buf << ",\n"
142
+ end
143
+ end
144
+
145
+ buf
146
+ end
147
+
148
+ def get_field(name)
149
+ @fields.find { |f| name == f.name }
150
+ end
151
+
152
+ def include(i)
153
+ @includes << i
154
+ end
155
+
156
+ def name(n)
157
+ @struct_name = n
158
+ end
159
+
160
+ end
161
+
162
+ ##
163
+ # A field in a Struct.
164
+
165
+ class StructGenerator::Field
166
+
167
+ attr_reader :name
168
+ attr_reader :type
169
+ attr_reader :offset
170
+ attr_accessor :size
171
+
172
+ def initialize(name, type)
173
+ @name = name
174
+ @type = type
175
+ @offset = nil
176
+ @size = nil
177
+ end
178
+
179
+ def offset=(o)
180
+ @offset = o
181
+ end
182
+
183
+ def to_config(name)
184
+ buf = []
185
+ buf << "rbx.platform.#{name}.#{@name}.offset = #{@offset}"
186
+ buf << "rbx.platform.#{name}.#{@name}.size = #{@size}"
187
+ buf << "rbx.platform.#{name}.#{@name}.type = #{@type}" if @type
188
+ buf
189
+ end
190
+
191
+ end
192
+
193
+ end
194
+
@@ -0,0 +1,137 @@
1
+ require 'tempfile'
2
+
3
+ module FFI
4
+
5
+ # @private
6
+ class TypesGenerator
7
+
8
+ ##
9
+ # Maps different C types to the C type representations we use
10
+
11
+ TYPE_MAP = {
12
+ "char" => :char,
13
+ "signed char" => :char,
14
+ "__signed char" => :char,
15
+ "unsigned char" => :uchar,
16
+
17
+ "short" => :short,
18
+ "signed short" => :short,
19
+ "signed short int" => :short,
20
+ "unsigned short" => :ushort,
21
+ "unsigned short int" => :ushort,
22
+
23
+ "int" => :int,
24
+ "signed int" => :int,
25
+ "unsigned int" => :uint,
26
+
27
+ "long" => :long,
28
+ "long int" => :long,
29
+ "signed long" => :long,
30
+ "signed long int" => :long,
31
+ "unsigned long" => :ulong,
32
+ "unsigned long int" => :ulong,
33
+ "long unsigned int" => :ulong,
34
+
35
+ "long long" => :long_long,
36
+ "long long int" => :long_long,
37
+ "signed long long" => :long_long,
38
+ "signed long long int" => :long_long,
39
+ "unsigned long long" => :ulong_long,
40
+ "unsigned long long int" => :ulong_long,
41
+
42
+ "char *" => :string,
43
+ "void *" => :pointer,
44
+ }
45
+
46
+ def self.generate(options = {})
47
+ typedefs = nil
48
+ Tempfile.open 'ffi_types_generator' do |io|
49
+ io.puts <<-C
50
+ #include <stdint.h>
51
+ #include <stddef.h>
52
+ #include <sys/types.h>
53
+ #if !(defined(WIN32))
54
+ #include <sys/socket.h>
55
+ #include <netinet/in.h>
56
+ #include <sys/resource.h>
57
+ #endif
58
+ C
59
+
60
+ io.close
61
+ cc = ENV['CC'] || 'gcc'
62
+ cmd = "#{cc} -E -x c #{options[:cppflags]} -D_DARWIN_USE_64_BIT_INODE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -c"
63
+ if options[:input]
64
+ typedefs = File.read(options[:input])
65
+ elsif options[:remote]
66
+ typedefs = `ssh #{options[:remote]} #{cmd} - < #{io.path}`
67
+ else
68
+ typedefs = `#{cmd} #{io.path}`
69
+ end
70
+ end
71
+
72
+ code = []
73
+
74
+ typedefs.each_line do |type|
75
+ # We only care about single line typedef
76
+ next unless type =~ /typedef/
77
+ # Ignore unions or structs
78
+ next if type =~ /union|struct/
79
+
80
+ # strip off the starting typedef and ending ;
81
+ type.gsub!(/^(.*typedef\s*)/, "")
82
+ type.gsub!(/\s*;\s*$/, "")
83
+
84
+ parts = type.split(/\s+/)
85
+ def_type = parts.join(" ")
86
+
87
+ # GCC does mapping with __attribute__ stuf, also see
88
+ # http://hal.cs.berkeley.edu/cil/cil016.html section 16.2.7. Problem
89
+ # with this is that the __attribute__ stuff can either occur before or
90
+ # after the new type that is defined...
91
+ if type =~ /__attribute__/
92
+ if parts.last =~ /__QI__|__HI__|__SI__|__DI__|__word__/
93
+
94
+ # In this case, the new type is BEFORE __attribute__ we need to
95
+ # find the final_type as the type before the part that starts with
96
+ # __attribute__
97
+ final_type = ""
98
+ parts.each do |p|
99
+ break if p =~ /__attribute__/
100
+ final_type = p
101
+ end
102
+ else
103
+ final_type = parts.pop
104
+ end
105
+
106
+ def_type = case type
107
+ when /__QI__/ then "char"
108
+ when /__HI__/ then "short"
109
+ when /__SI__/ then "int"
110
+ when /__DI__/ then "long long"
111
+ when /__word__/ then "long"
112
+ else "int"
113
+ end
114
+
115
+ def_type = "unsigned #{def_type}" if type =~ /unsigned/
116
+ else
117
+ final_type = parts.pop
118
+ def_type = parts.join(" ")
119
+ end
120
+
121
+ if type = TYPE_MAP[def_type]
122
+ code << "rbx.platform.typedef.#{final_type} = #{type}"
123
+ TYPE_MAP[final_type] = TYPE_MAP[def_type]
124
+ else
125
+ # Fallback to an ordinary pointer if we don't know the type
126
+ if def_type =~ /\*/
127
+ code << "rbx.platform.typedef.#{final_type} = pointer"
128
+ TYPE_MAP[final_type] = :pointer
129
+ end
130
+ end
131
+ end
132
+
133
+ code.sort.join("\n")
134
+ end
135
+ end
136
+ end
137
+