fiddle 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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")