fiddle 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,11 +13,12 @@ typedef struct {
13
13
  ffi_type **argv;
14
14
  } fiddle_closure;
15
15
 
16
- #if defined(USE_FFI_CLOSURE_ALLOC)
17
- #elif defined(__OpenBSD__) || defined(__APPLE__) || defined(__linux__)
16
+ #if defined(__OpenBSD__)
18
17
  # define USE_FFI_CLOSURE_ALLOC 0
19
- #elif defined(RUBY_LIBFFI_MODVERSION) && RUBY_LIBFFI_MODVERSION < 3000005 && \
20
- (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_AMD64))
18
+ #endif
19
+
20
+ #if defined(USE_FFI_CLOSURE_ALLOC)
21
+ #elif !defined(HAVE_FFI_CLOSURE_ALLOC)
21
22
  # define USE_FFI_CLOSURE_ALLOC 0
22
23
  #else
23
24
  # define USE_FFI_CLOSURE_ALLOC 1
@@ -1,7 +1,115 @@
1
1
  #include <fiddle.h>
2
2
 
3
+ VALUE
4
+ rb_fiddle_type_ensure(VALUE type)
5
+ {
6
+ VALUE original_type = type;
7
+
8
+ if (!RB_SYMBOL_P(type)) {
9
+ VALUE type_string = rb_check_string_type(type);
10
+ if (!NIL_P(type_string)) {
11
+ type = rb_to_symbol(type_string);
12
+ }
13
+ }
14
+
15
+ if (RB_SYMBOL_P(type)) {
16
+ ID type_id = rb_sym2id(type);
17
+ ID void_id;
18
+ ID voidp_id;
19
+ ID char_id;
20
+ ID short_id;
21
+ ID int_id;
22
+ ID long_id;
23
+ #ifdef TYPE_LONG_LONG
24
+ ID long_long_id;
25
+ #endif
26
+ ID float_id;
27
+ ID double_id;
28
+ ID variadic_id;
29
+ ID const_string_id;
30
+ ID size_t_id;
31
+ ID ssize_t_id;
32
+ ID ptrdiff_t_id;
33
+ ID intptr_t_id;
34
+ ID uintptr_t_id;
35
+ RUBY_CONST_ID(void_id, "void");
36
+ RUBY_CONST_ID(voidp_id, "voidp");
37
+ RUBY_CONST_ID(char_id, "char");
38
+ RUBY_CONST_ID(short_id, "short");
39
+ RUBY_CONST_ID(int_id, "int");
40
+ RUBY_CONST_ID(long_id, "long");
41
+ #ifdef TYPE_LONG_LONG
42
+ RUBY_CONST_ID(long_long_id, "long_long");
43
+ #endif
44
+ RUBY_CONST_ID(float_id, "float");
45
+ RUBY_CONST_ID(double_id, "double");
46
+ RUBY_CONST_ID(variadic_id, "variadic");
47
+ RUBY_CONST_ID(const_string_id, "const_string");
48
+ RUBY_CONST_ID(size_t_id, "size_t");
49
+ RUBY_CONST_ID(ssize_t_id, "ssize_t");
50
+ RUBY_CONST_ID(ptrdiff_t_id, "ptrdiff_t");
51
+ RUBY_CONST_ID(intptr_t_id, "intptr_t");
52
+ RUBY_CONST_ID(uintptr_t_id, "uintptr_t");
53
+ if (type_id == void_id) {
54
+ return INT2NUM(TYPE_VOID);
55
+ }
56
+ else if (type_id == voidp_id) {
57
+ return INT2NUM(TYPE_VOIDP);
58
+ }
59
+ else if (type_id == char_id) {
60
+ return INT2NUM(TYPE_CHAR);
61
+ }
62
+ else if (type_id == short_id) {
63
+ return INT2NUM(TYPE_SHORT);
64
+ }
65
+ else if (type_id == int_id) {
66
+ return INT2NUM(TYPE_INT);
67
+ }
68
+ else if (type_id == long_id) {
69
+ return INT2NUM(TYPE_LONG);
70
+ }
71
+ #ifdef TYPE_LONG_LONG
72
+ else if (type_id == long_long_id) {
73
+ return INT2NUM(TYPE_LONG_LONG);
74
+ }
75
+ #endif
76
+ else if (type_id == float_id) {
77
+ return INT2NUM(TYPE_FLOAT);
78
+ }
79
+ else if (type_id == double_id) {
80
+ return INT2NUM(TYPE_DOUBLE);
81
+ }
82
+ else if (type_id == variadic_id) {
83
+ return INT2NUM(TYPE_VARIADIC);
84
+ }
85
+ else if (type_id == const_string_id) {
86
+ return INT2NUM(TYPE_CONST_STRING);
87
+ }
88
+ else if (type_id == size_t_id) {
89
+ return INT2NUM(TYPE_SIZE_T);
90
+ }
91
+ else if (type_id == ssize_t_id) {
92
+ return INT2NUM(TYPE_SSIZE_T);
93
+ }
94
+ else if (type_id == ptrdiff_t_id) {
95
+ return INT2NUM(TYPE_PTRDIFF_T);
96
+ }
97
+ else if (type_id == intptr_t_id) {
98
+ return INT2NUM(TYPE_INTPTR_T);
99
+ }
100
+ else if (type_id == uintptr_t_id) {
101
+ return INT2NUM(TYPE_UINTPTR_T);
102
+ }
103
+ else {
104
+ type = original_type;
105
+ }
106
+ }
107
+
108
+ return rb_to_int(type);
109
+ }
110
+
3
111
  ffi_type *
4
- int_to_ffi_type(int type)
112
+ rb_fiddle_int_to_ffi_type(int type)
5
113
  {
6
114
  int signed_p = 1;
7
115
 
@@ -33,66 +141,90 @@ int_to_ffi_type(int type)
33
141
  return &ffi_type_float;
34
142
  case TYPE_DOUBLE:
35
143
  return &ffi_type_double;
144
+ case TYPE_CONST_STRING:
145
+ return &ffi_type_pointer;
36
146
  default:
37
147
  rb_raise(rb_eRuntimeError, "unknown type %d", type);
38
148
  }
39
149
  return &ffi_type_pointer;
40
150
  }
41
151
 
152
+ ffi_type *
153
+ int_to_ffi_type(int type)
154
+ {
155
+ return rb_fiddle_int_to_ffi_type(type);
156
+ }
157
+
42
158
  void
43
- value_to_generic(int type, VALUE src, fiddle_generic * dst)
159
+ rb_fiddle_value_to_generic(int type, VALUE *src, fiddle_generic *dst)
44
160
  {
45
161
  switch (type) {
46
162
  case TYPE_VOID:
47
163
  break;
48
164
  case TYPE_VOIDP:
49
- dst->pointer = NUM2PTR(rb_Integer(src));
165
+ dst->pointer = NUM2PTR(rb_Integer(*src));
50
166
  break;
51
167
  case TYPE_CHAR:
52
- dst->schar = (signed char)NUM2INT(src);
168
+ dst->schar = (signed char)NUM2INT(*src);
53
169
  break;
54
170
  case -TYPE_CHAR:
55
- dst->uchar = (unsigned char)NUM2UINT(src);
171
+ dst->uchar = (unsigned char)NUM2UINT(*src);
56
172
  break;
57
173
  case TYPE_SHORT:
58
- dst->sshort = (unsigned short)NUM2INT(src);
174
+ dst->sshort = (unsigned short)NUM2INT(*src);
59
175
  break;
60
176
  case -TYPE_SHORT:
61
- dst->sshort = (signed short)NUM2UINT(src);
177
+ dst->sshort = (signed short)NUM2UINT(*src);
62
178
  break;
63
179
  case TYPE_INT:
64
- dst->sint = NUM2INT(src);
180
+ dst->sint = NUM2INT(*src);
65
181
  break;
66
182
  case -TYPE_INT:
67
- dst->uint = NUM2UINT(src);
183
+ dst->uint = NUM2UINT(*src);
68
184
  break;
69
185
  case TYPE_LONG:
70
- dst->slong = NUM2LONG(src);
186
+ dst->slong = NUM2LONG(*src);
71
187
  break;
72
188
  case -TYPE_LONG:
73
- dst->ulong = NUM2ULONG(src);
189
+ dst->ulong = NUM2ULONG(*src);
74
190
  break;
75
191
  #if HAVE_LONG_LONG
76
192
  case TYPE_LONG_LONG:
77
- dst->slong_long = NUM2LL(src);
193
+ dst->slong_long = NUM2LL(*src);
78
194
  break;
79
195
  case -TYPE_LONG_LONG:
80
- dst->ulong_long = NUM2ULL(src);
196
+ dst->ulong_long = NUM2ULL(*src);
81
197
  break;
82
198
  #endif
83
199
  case TYPE_FLOAT:
84
- dst->ffloat = (float)NUM2DBL(src);
200
+ dst->ffloat = (float)NUM2DBL(*src);
85
201
  break;
86
202
  case TYPE_DOUBLE:
87
- dst->ddouble = NUM2DBL(src);
203
+ dst->ddouble = NUM2DBL(*src);
204
+ break;
205
+ case TYPE_CONST_STRING:
206
+ if (NIL_P(*src)) {
207
+ dst->pointer = NULL;
208
+ }
209
+ else {
210
+ dst->pointer = rb_string_value_cstr(src);
211
+ }
88
212
  break;
89
213
  default:
90
214
  rb_raise(rb_eRuntimeError, "unknown type %d", type);
91
215
  }
92
216
  }
93
217
 
218
+ void
219
+ value_to_generic(int type, VALUE src, fiddle_generic *dst)
220
+ {
221
+ /* src isn't safe from GC when type is TYPE_CONST_STRING and src
222
+ * isn't String. */
223
+ return rb_fiddle_value_to_generic(type, &src, dst);
224
+ }
225
+
94
226
  VALUE
95
- generic_to_value(VALUE rettype, fiddle_generic retval)
227
+ rb_fiddle_generic_to_value(VALUE rettype, fiddle_generic retval)
96
228
  {
97
229
  int type = NUM2INT(rettype);
98
230
  VALUE cPointer;
@@ -131,6 +263,13 @@ generic_to_value(VALUE rettype, fiddle_generic retval)
131
263
  return rb_float_new(retval.ffloat);
132
264
  case TYPE_DOUBLE:
133
265
  return rb_float_new(retval.ddouble);
266
+ case TYPE_CONST_STRING:
267
+ if (retval.pointer) {
268
+ return rb_str_new_cstr(retval.pointer);
269
+ }
270
+ else {
271
+ return Qnil;
272
+ }
134
273
  default:
135
274
  rb_raise(rb_eRuntimeError, "unknown type %d", type);
136
275
  }
@@ -138,4 +277,10 @@ generic_to_value(VALUE rettype, fiddle_generic retval)
138
277
  UNREACHABLE;
139
278
  }
140
279
 
280
+ VALUE
281
+ generic_to_value(VALUE rettype, fiddle_generic retval)
282
+ {
283
+ return rb_fiddle_generic_to_value(rettype, retval);
284
+ }
285
+
141
286
  /* vim: set noet sw=4 sts=4 */
@@ -24,13 +24,23 @@ typedef union
24
24
  void * pointer; /* ffi_type_pointer */
25
25
  } fiddle_generic;
26
26
 
27
+ /* Deprecated. Use rb_fiddle_*() version. */
28
+ VALUE rb_fiddle_type_ensure(VALUE type);
29
+ ffi_type * rb_fiddle_int_to_ffi_type(int type);
30
+ void rb_fiddle_value_to_generic(int type, VALUE *src, fiddle_generic *dst);
31
+ VALUE rb_fiddle_generic_to_value(VALUE rettype, fiddle_generic retval);
32
+
33
+ /* Deprecated. Use rb_fiddle_*() version. */
27
34
  ffi_type * int_to_ffi_type(int type);
28
- void value_to_generic(int type, VALUE src, fiddle_generic * dst);
35
+ void value_to_generic(int type, VALUE src, fiddle_generic *dst);
29
36
  VALUE generic_to_value(VALUE rettype, fiddle_generic retval);
30
37
 
31
- #define VALUE2GENERIC(_type, _src, _dst) value_to_generic((_type), (_src), (_dst))
32
- #define INT2FFI_TYPE(_type) int_to_ffi_type(_type)
33
- #define GENERIC2VALUE(_type, _retval) generic_to_value((_type), (_retval))
38
+ #define VALUE2GENERIC(_type, _src, _dst) \
39
+ rb_fiddle_value_to_generic((_type), &(_src), (_dst))
40
+ #define INT2FFI_TYPE(_type) \
41
+ rb_fiddle_int_to_ffi_type(_type)
42
+ #define GENERIC2VALUE(_type, _retval) \
43
+ rb_fiddle_generic_to_value((_type), (_retval))
34
44
 
35
45
  #if SIZEOF_VOIDP == SIZEOF_LONG
36
46
  # define PTR2NUM(x) (LONG2NUM((long)(x)))
@@ -0,0 +1,83 @@
1
+ PWD =
2
+
3
+ CONFIGURE_LIBFFI = \
4
+ $(LIBFFI_CONFIGURE) --disable-shared \
5
+ --host=$(LIBFFI_ARCH) --enable-builddir=$(arch) \
6
+ CC="$(CC)" CFLAGS="$(LIBFFI_CFLAGS)" \
7
+ LD="$(LD)" LDFLAGS="$(LIBFFI_LDFLAGS)"
8
+
9
+ $(STATIC_LIB) $(RUBYARCHDIR)/$(DLLIB) $(DLLIB): $(LIBFFI_A)
10
+
11
+ $(OBJS): $(FFI_H)
12
+
13
+ .PHONY: .FORCE hdr
14
+
15
+ .FORCE:
16
+
17
+ hdr: $(FFI_H)
18
+
19
+ configure-libffi build-libffi: .FORCE
20
+ configure-libffi \
21
+ $(LIBFFI_DIR)/include/ffi.h \
22
+ $(LIBFFI_DIR)/include/ffitarget.h \
23
+ $(LIBFFI_DIR)/fficonfig.h \
24
+ $(LIBFFI_DIR)/Makefile:
25
+ $(Q) $(MAKEDIRS) $(LIBFFI_DIR)
26
+ $(Q) $(CONFIGURE_LIBFFI)
27
+
28
+ build-libffi $(LIBFFI_A):
29
+ $(Q) $(SUBMAKE_PRE) $(MAKE) $(SUBMAKE_ARG)
30
+
31
+ clean-none:
32
+ clean-libffi:
33
+ $(Q) $(SUBMAKE_PRE) $(MAKE) $(SUBMAKE_ARG) clean
34
+
35
+ distclean-none:
36
+ distclean-libffi:
37
+ $(Q) $(SUBMAKE_PRE) $(MAKE) $(SUBMAKE_ARG) distclean
38
+ $(Q) $(RM) $(LIBFFI_DIR)/local.exp
39
+ $(Q) $(RUBY) -rfileutils -e "FileUtils.rmdir(Dir.glob(ARGV[0]+'/**/{,.*/}'), :parents=>true)" $(LIBFFI_DIR)
40
+
41
+ realclean-none:
42
+ realclean-libffi:
43
+ $(Q) $(RMALL) $(LIBFFI_DIR)
44
+
45
+ .PHONY: clean-libffi distclean-libffi realclean-libffi
46
+ .PHONY: clean-none distclean-none realclean-none
47
+
48
+ clean: clean-$(LIBFFI_CLEAN)
49
+ distclean: distclean-$(LIBFFI_CLEAN)
50
+ realclean: realclean-$(LIBFFI_CLEAN)
51
+
52
+ .PHONY: configure configure-libffi
53
+
54
+ closure.o: closure.c
55
+ closure.o: closure.h
56
+ closure.o: conversions.h
57
+ closure.o: fiddle.h
58
+ closure.o: function.h
59
+ conversions.o: closure.h
60
+ conversions.o: conversions.c
61
+ conversions.o: conversions.h
62
+ conversions.o: fiddle.h
63
+ conversions.o: function.h
64
+ fiddle.o: closure.h
65
+ fiddle.o: conversions.h
66
+ fiddle.o: fiddle.c
67
+ fiddle.o: fiddle.h
68
+ fiddle.o: function.h
69
+ function.o: closure.h
70
+ function.o: conversions.h
71
+ function.o: fiddle.h
72
+ function.o: function.c
73
+ function.o: function.h
74
+ handle.o: closure.h
75
+ handle.o: conversions.h
76
+ handle.o: fiddle.h
77
+ handle.o: function.h
78
+ handle.o: handle.c
79
+ pointer.o: closure.h
80
+ pointer.o: conversions.h
81
+ pointer.o: fiddle.h
82
+ pointer.o: function.h
83
+ pointer.o: pointer.c
@@ -3,22 +3,32 @@ require 'mkmf'
3
3
 
4
4
  # :stopdoc:
5
5
 
6
+ libffi_version = nil
7
+ have_libffi = false
6
8
  bundle = enable_config('bundled-libffi')
7
- if ! bundle
9
+ unless bundle
8
10
  dir_config 'libffi'
9
11
 
10
- pkg_config("libffi") and
11
- ver = pkg_config("libffi", "modversion")
12
+ if pkg_config("libffi")
13
+ libffi_version = pkg_config("libffi", "modversion")
14
+ end
12
15
 
16
+ have_ffi_header = false
13
17
  if have_header(ffi_header = 'ffi.h')
14
- true
18
+ have_ffi_header = true
15
19
  elsif have_header(ffi_header = 'ffi/ffi.h')
16
- $defs.push(format('-DUSE_HEADER_HACKS'))
17
- true
18
- end and (have_library('ffi') || have_library('libffi'))
19
- end or
20
- begin
21
- if bundle
20
+ $defs.push('-DUSE_HEADER_HACKS')
21
+ have_ffi_header = true
22
+ end
23
+ if have_ffi_header && (have_library('ffi') || have_library('libffi'))
24
+ have_libffi = true
25
+ end
26
+ end
27
+
28
+ unless have_libffi
29
+ # for https://github.com/ruby/fiddle
30
+ extlibs_rb = File.expand_path("../../bin/extlibs.rb", $srcdir)
31
+ if bundle && File.exist?(extlibs_rb)
22
32
  require "fileutils"
23
33
  require_relative "../../bin/extlibs"
24
34
  extlibs = ExtLibs.new
@@ -27,31 +37,32 @@ begin
27
37
  Dir.glob("#{$srcdir}/libffi-*/").each{|dir| FileUtils.rm_rf(dir)}
28
38
  extlibs.run(["--cache=#{cache_dir}", ext_dir])
29
39
  end
30
- ver = bundle != false &&
31
- Dir.glob("#{$srcdir}/libffi-*/")
32
- .map {|n| File.basename(n)}
33
- .max_by {|n| n.scan(/\d+/).map(&:to_i)}
34
- unless ver
40
+ if bundle != false
41
+ libffi_package_name = Dir.glob("#{$srcdir}/libffi-*/")
42
+ .map {|n| File.basename(n)}
43
+ .max_by {|n| n.scan(/\d+/).map(&:to_i)}
44
+ end
45
+ unless libffi_package_name
35
46
  raise "missing libffi. Please install libffi."
36
47
  end
37
48
 
38
- srcdir = "#{$srcdir}/#{ver}"
49
+ libffi_srcdir = "#{$srcdir}/#{libffi_package_name}"
39
50
  ffi_header = 'ffi.h'
40
51
  libffi = Struct.new(*%I[dir srcdir builddir include lib a cflags ldflags opt arch]).new
41
- libffi.dir = ver
52
+ libffi.dir = libffi_package_name
42
53
  if $srcdir == "."
43
- libffi.builddir = "#{ver}/#{RUBY_PLATFORM}"
54
+ libffi.builddir = libffi_package_name
44
55
  libffi.srcdir = "."
45
56
  else
46
57
  libffi.builddir = libffi.dir
47
- libffi.srcdir = relative_from(srcdir, "..")
58
+ libffi.srcdir = relative_from(libffi_srcdir, "..")
48
59
  end
49
60
  libffi.include = "#{libffi.builddir}/include"
50
61
  libffi.lib = "#{libffi.builddir}/.libs"
51
62
  libffi.a = "#{libffi.lib}/libffi_convenience.#{$LIBEXT}"
52
63
  nowarn = CONFIG.merge("warnflags"=>"")
53
64
  libffi.cflags = RbConfig.expand("$(CFLAGS)".dup, nowarn)
54
- ver = ver[/libffi-(.*)/, 1]
65
+ libffi_version = libffi_package_name[/libffi-(.*)/, 1]
55
66
 
56
67
  FileUtils.mkdir_p(libffi.dir)
57
68
  libffi.opt = CONFIG['configure_args'][/'(-C)'/, 1]
@@ -80,7 +91,6 @@ begin
80
91
  args.concat %W[
81
92
  --srcdir=#{libffi.srcdir}
82
93
  --host=#{libffi.arch}
83
- --enable-builddir=#{RUBY_PLATFORM}
84
94
  ]
85
95
  args << ($enable_shared || !$static ? '--enable-shared' : '--enable-static')
86
96
  args << libffi.opt if libffi.opt
@@ -97,7 +107,7 @@ begin
97
107
  begin
98
108
  IO.copy_stream(libffi.dir + "/config.log", Logging.instance_variable_get(:@logfile))
99
109
  rescue SystemCallError => e
100
- Logfile.message("%s\n", e.message)
110
+ Logging.message("%s\n", e.message)
101
111
  end
102
112
  raise "failed to configure libffi. Please install libffi."
103
113
  end
@@ -106,15 +116,31 @@ begin
106
116
  FileUtils.rm_f("#{libffi.include}/ffitarget.h")
107
117
  end
108
118
  unless File.file?("#{libffi.include}/ffitarget.h")
109
- FileUtils.cp("#{srcdir}/src/x86/ffitarget.h", libffi.include, preserve: true)
119
+ FileUtils.cp("#{libffi_srcdir}/src/x86/ffitarget.h", libffi.include, preserve: true)
110
120
  end
111
121
  $INCFLAGS << " -I" << libffi.include
112
122
  end
113
123
 
114
- if ver
115
- ver = ver.gsub(/-rc\d+/, '') # If ver contains rc version, just ignored.
116
- ver = (ver.split('.') + [0,0])[0,3]
117
- $defs.push(%{-DRUBY_LIBFFI_MODVERSION=#{ '%d%03d%03d' % ver }})
124
+ if libffi_version
125
+ # If libffi_version contains rc version, just ignored.
126
+ libffi_version = libffi_version.gsub(/-rc\d+/, '')
127
+ libffi_version = (libffi_version.split('.').map(&:to_i) + [0,0])[0,3]
128
+ $defs.push(%{-DRUBY_LIBFFI_MODVERSION=#{ '%d%03d%03d' % libffi_version }})
129
+ warn "libffi_version: #{libffi_version.join('.')}"
130
+ end
131
+
132
+ case
133
+ when $mswin, $mingw, (libffi_version && (libffi_version <=> [3, 2]) >= 0)
134
+ $defs << "-DUSE_FFI_CLOSURE_ALLOC=1"
135
+ when (libffi_version && (libffi_version <=> [3, 2]) < 0)
136
+ else
137
+ have_func('ffi_closure_alloc', ffi_header)
138
+ end
139
+
140
+ if libffi
141
+ $defs << "-DHAVE_FFI_PREP_CIF_VAR"
142
+ else
143
+ have_func('ffi_prep_cif_var', ffi_header)
118
144
  end
119
145
 
120
146
  have_header 'sys/mman.h'
@@ -141,7 +167,7 @@ types.each do |type, signed|
141
167
  if /^\#define\s+SIZEOF_#{type}\s+(SIZEOF_(.+)|\d+)/ =~ config
142
168
  if size = $2 and size != 'VOIDP'
143
169
  size = types.fetch(size) {size}
144
- $defs << format("-DTYPE_%s=TYPE_%s", signed||type, size)
170
+ $defs << "-DTYPE_#{signed||type}=TYPE_#{size}"
145
171
  end
146
172
  if signed
147
173
  check_signedness(type.downcase, "stddef.h")