ffi 1.3.1-x86-mingw32 → 1.4.0-x86-mingw32

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.

data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # ruby-ffi http://wiki.github.com/ffi/ffi
1
+ # ruby-ffi http://wiki.github.com/ffi/ffi [![Build Status](https://travis-ci.org/ffi/ffi.png?branch=master)](https://travis-ci.org/ffi/ffi)
2
2
 
3
3
  ## Description
4
4
 
@@ -271,8 +271,10 @@ typedef struct BlockingCall_ {
271
271
  FunctionType* info;
272
272
  void **ffiValues;
273
273
  void* retval;
274
- void* stkretval;
275
274
  void* params;
275
+ #if !(defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL))
276
+ void* stkretval;
277
+ #endif
276
278
  } BlockingCall;
277
279
 
278
280
  static VALUE
@@ -285,6 +287,8 @@ call_blocking_function(void* data)
285
287
  return Qnil;
286
288
  }
287
289
 
290
+ #if !(defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL))
291
+
288
292
  static VALUE
289
293
  do_blocking_call(void *data)
290
294
  {
@@ -307,17 +311,16 @@ cleanup_blocking_call(void *data)
307
311
  return Qnil;
308
312
  }
309
313
 
314
+ #endif /* HAVE_RB_THREAD_BLOCKING_REGION */
315
+
310
316
  VALUE
311
317
  rbffi_CallFunction(int argc, VALUE* argv, void* function, FunctionType* fnInfo)
312
318
  {
313
319
  void* retval;
314
320
  void** ffiValues;
315
321
  FFIStorage* params;
316
- VALUE rbReturnValue;
317
-
318
- #if !defined(HAVE_RUBY_THREAD_HAS_GVL_P)
322
+ VALUE rbReturnValue, exc;
319
323
  rbffi_thread_t oldThread;
320
- #endif
321
324
 
322
325
  retval = alloca(MAX(fnInfo->ffi_cif.rtype->size, FFI_SIZEOF_ARG));
323
326
 
@@ -328,21 +331,36 @@ rbffi_CallFunction(int argc, VALUE* argv, void* function, FunctionType* fnInfo)
328
331
  * due to the way thread switching works on older ruby variants, we
329
332
  * cannot allocate anything passed to the blocking function on the stack
330
333
  */
334
+ #if defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
335
+ ffiValues = ALLOCA_N(void *, fnInfo->parameterCount);
336
+ params = ALLOCA_N(FFIStorage, fnInfo->parameterCount);
337
+ bc = ALLOCA_N(BlockingCall, 1);
338
+ bc->retval = retval;
339
+ #else
331
340
  ffiValues = ALLOC_N(void *, fnInfo->parameterCount);
332
341
  params = ALLOC_N(FFIStorage, fnInfo->parameterCount);
333
342
  bc = ALLOC_N(BlockingCall, 1);
343
+ bc->retval = xmalloc(MAX(fnInfo->ffi_cif.rtype->size, FFI_SIZEOF_ARG));
344
+ bc->stkretval = retval;
345
+ #endif
334
346
  bc->info = fnInfo;
335
347
  bc->function = function;
336
348
  bc->ffiValues = ffiValues;
337
349
  bc->params = params;
338
- bc->retval = xmalloc(MAX(fnInfo->ffi_cif.rtype->size, FFI_SIZEOF_ARG));
339
- bc->stkretval = retval;
340
350
 
341
351
  rbffi_SetupCallParams(argc, argv,
342
352
  fnInfo->parameterCount, fnInfo->parameterTypes, params, ffiValues,
343
353
  fnInfo->callbackParameters, fnInfo->callbackCount, fnInfo->rbEnums);
344
-
354
+
355
+ #if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
356
+ rb_thread_call_without_gvl(call_blocking_function, bc, (void *) -1, NULL);
357
+
358
+ #elif defined(HAVE_RB_THREAD_BLOCKING_REGION)
359
+ rb_thread_blocking_region(call_blocking_function, bc, (void *) -1, NULL);
360
+
361
+ #else
345
362
  rb_ensure(do_blocking_call, (VALUE) bc, cleanup_blocking_call, (VALUE) bc);
363
+ #endif
346
364
 
347
365
  } else {
348
366
 
@@ -353,15 +371,16 @@ rbffi_CallFunction(int argc, VALUE* argv, void* function, FunctionType* fnInfo)
353
371
  fnInfo->parameterCount, fnInfo->parameterTypes, params, ffiValues,
354
372
  fnInfo->callbackParameters, fnInfo->callbackCount, fnInfo->rbEnums);
355
373
 
356
- #if !defined(HAVE_RUBY_THREAD_HAS_GVL_P)
357
374
  oldThread = rbffi_active_thread;
358
375
  rbffi_active_thread = rbffi_thread_self();
359
- #endif
376
+
360
377
  ffi_call(&fnInfo->ffi_cif, FFI_FN(function), retval, ffiValues);
361
378
 
362
- #if !defined(HAVE_RUBY_THREAD_HAS_GVL_P)
379
+ exc = rbffi_active_thread.exc;
363
380
  rbffi_active_thread = oldThread;
364
- #endif
381
+ if (exc != Qnil) {
382
+ rb_exc_raise(exc);
383
+ }
365
384
  }
366
385
 
367
386
  if (unlikely(!fnInfo->ignoreErrno)) {
@@ -23,7 +23,7 @@
23
23
  #ifndef _MSC_VER
24
24
  # include <stdint.h>
25
25
  #endif
26
- #if defined(_WIN32) || defined(__WIN32__)
26
+ #if (defined(_WIN32) || defined(__WIN32__)) && !defined(__CYGWIN__)
27
27
  # include <winsock2.h>
28
28
  # define _WINSOCKAPI_
29
29
  # include <windows.h>
@@ -59,7 +59,7 @@ static void symbol_mark(LibrarySymbol* sym);
59
59
 
60
60
  static VALUE LibraryClass = Qnil, SymbolClass = Qnil;
61
61
 
62
- #if defined(_WIN32) || defined(__WIN32__)
62
+ #if (defined(_WIN32) || defined(__WIN32__)) && !defined(__CYGWIN__)
63
63
  static void* dl_open(const char* name, int flags);
64
64
  static void dl_error(char* buf, int size);
65
65
  #define dl_sym(handle, name) GetProcAddress(handle, name)
@@ -123,6 +123,15 @@ library_initialize(VALUE self, VALUE libname, VALUE libflags)
123
123
  libname != Qnil ? StringValueCStr(libname) : "[current process]",
124
124
  errmsg);
125
125
  }
126
+ #ifdef __CYGWIN__
127
+ // On Cygwin 1.7.17 "dlsym(dlopen(0,0), 'getpid')" fails. (dlerror: "No such process")
128
+ // As a workaround we can use "dlsym(RTLD_DEFAULT, 'getpid')" instead.
129
+ // Since 0 == RTLD_DEFAULT we won't call dl_close later.
130
+ if (libname == Qnil) {
131
+ dl_close(library->handle);
132
+ library->handle = RTLD_DEFAULT;
133
+ }
134
+ #endif
126
135
  rb_iv_set(self, "@name", libname != Qnil ? libname : rb_str_new2("[current process]"));
127
136
  return self;
128
137
  }
@@ -164,7 +173,7 @@ library_free(Library* library)
164
173
  xfree(library);
165
174
  }
166
175
 
167
- #if defined(_WIN32) || defined(__WIN32__)
176
+ #if (defined(_WIN32) || defined(__WIN32__)) && !defined(__CYGWIN__)
168
177
  static void*
169
178
  dl_open(const char* name, int flags)
170
179
  {
@@ -78,7 +78,8 @@ static void function_free(Function *);
78
78
  static VALUE function_init(VALUE self, VALUE rbFunctionInfo, VALUE rbProc);
79
79
  static void callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data);
80
80
  static bool callback_prep(void* ctx, void* code, Closure* closure, char* errmsg, size_t errmsgsize);
81
- static void* callback_with_gvl(void* data);
81
+ static VALUE callback_with_gvl(void* data);
82
+ static VALUE save_callback_exception(void* data, VALUE exc);
82
83
 
83
84
  #define DEFER_ASYNC_CALLBACK 1
84
85
 
@@ -458,12 +459,9 @@ callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data)
458
459
  cb.done = false;
459
460
 
460
461
  if (rbffi_thread_has_gvl_p()) {
461
- callback_with_gvl(&cb);
462
+ rbffi_active_thread.exc = Qnil;
463
+ rb_rescue2(callback_with_gvl, &cb, save_callback_exception, &cb, rb_eException, (VALUE) 0);
462
464
 
463
- #if defined(HAVE_RUBY_NATIVE_THREAD_P) && defined (HAVE_RB_THREAD_CALL_WITH_GVL)
464
- } else if (ruby_native_thread_p()) {
465
- rb_thread_call_with_gvl(callback_with_gvl, &cb);
466
- #endif
467
465
  #if defined(DEFER_ASYNC_CALLBACK) && !defined(_WIN32)
468
466
  } else {
469
467
  bool empty = false;
@@ -536,7 +534,7 @@ struct async_wait {
536
534
  static VALUE async_cb_wait(void *);
537
535
  static void async_cb_stop(void *);
538
536
 
539
- #if defined(HAVE_RB_THREAD_BLOCKING_REGION)
537
+ #if defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
540
538
  static VALUE
541
539
  async_cb_event(void* unused)
542
540
  {
@@ -544,7 +542,11 @@ async_cb_event(void* unused)
544
542
 
545
543
  w.stop = false;
546
544
  while (!w.stop) {
545
+ #if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
546
+ rb_thread_call_without_gvl(async_cb_wait, &w, async_cb_stop, &w);
547
+ #else
547
548
  rb_thread_blocking_region(async_cb_wait, &w, async_cb_stop, &w);
549
+ #endif
548
550
  if (w.cb != NULL) {
549
551
  /* Start up a new ruby thread to run the ruby callback */
550
552
  rb_thread_create(async_cb_call, w.cb);
@@ -713,7 +715,7 @@ async_cb_call(void *data)
713
715
  #endif
714
716
 
715
717
 
716
- static void*
718
+ static VALUE
717
719
  callback_with_gvl(void* data)
718
720
  {
719
721
  struct gvl_callback* cb = (struct gvl_callback *) data;
@@ -901,9 +903,19 @@ callback_with_gvl(void* data)
901
903
  break;
902
904
  }
903
905
 
904
- return NULL;
906
+ return Qnil;
905
907
  }
906
908
 
909
+ static VALUE
910
+ save_callback_exception(void* data, VALUE exc)
911
+ {
912
+ struct gvl_callback* cb = (struct gvl_callback *) data;
913
+
914
+ memset(cb->retval, 0, ((Function *) cb->closure->info)->info->returnType->ffiType->size);
915
+ rbffi_active_thread.exc = exc;
916
+
917
+ return Qnil;
918
+ }
907
919
 
908
920
  static bool
909
921
  callback_prep(void* ctx, void* code, Closure* closure, char* errmsg, size_t errmsgsize)
@@ -39,7 +39,6 @@ typedef int bool;
39
39
  #include "Thread.h"
40
40
 
41
41
 
42
- #ifndef HAVE_RUBY_THREAD_HAS_GVL_P
43
42
  rbffi_thread_t rbffi_active_thread;
44
43
 
45
44
  rbffi_thread_t
@@ -52,6 +51,7 @@ rbffi_thread_self()
52
51
  self.id = pthread_self();
53
52
  #endif
54
53
  self.valid = true;
54
+ self.exc = Qnil;
55
55
 
56
56
  return self;
57
57
  }
@@ -76,7 +76,6 @@ rbffi_thread_has_gvl_p(void)
76
76
  return rbffi_active_thread.valid && pthread_equal(rbffi_active_thread.id, pthread_self());
77
77
  #endif
78
78
  }
79
- #endif /* HAVE_RUBY_THREAD_HAS_GVL_P */
80
79
 
81
80
  #ifndef HAVE_RB_THREAD_BLOCKING_REGION
82
81
 
@@ -292,34 +291,6 @@ rbffi_thread_blocking_region(VALUE (*func)(void *), void *data1, void (*ubf)(voi
292
291
  return thr->retval;
293
292
  }
294
293
 
295
-
296
- #if 0
297
-
298
- /*
299
- * FIXME: someone needs to implement something similar to the posix pipe based
300
- * blocking region implementation above for ruby1.8.x on win32
301
- */
302
- VALUE
303
- rbffi_thread_blocking_region(VALUE (*func)(void *), void *data1, void (*ubf)(void *), void *data2)
304
- {
305
- #if !defined(HAVE_RUBY_THREAD_HAS_GVL_P)
306
- rbffi_thread_t oldThread;
307
- #endif
308
- VALUE res;
309
- #if !defined(HAVE_RUBY_THREAD_HAS_GVL_P)
310
- oldThread = rbffi_active_thread;
311
- rbffi_active_thread = rbffi_thread_self();
312
- #endif
313
-
314
- res = (*func)(data1);
315
-
316
- #if !defined(HAVE_RUBY_THREAD_HAS_GVL_P)
317
- rbffi_active_thread = oldThread;
318
- #endif
319
- return res;
320
- }
321
- #endif
322
-
323
294
  #endif /* !_WIN32 */
324
295
 
325
296
  #endif /* HAVE_RB_THREAD_BLOCKING_REGION */
@@ -54,6 +54,7 @@ typedef struct {
54
54
  pthread_t id;
55
55
  #endif
56
56
  bool valid;
57
+ VALUE exc;
57
58
  } rbffi_thread_t;
58
59
 
59
60
  extern rbffi_thread_t rbffi_active_thread;
@@ -163,9 +163,9 @@ variadic_invoke(VALUE self, VALUE parameterTypes, VALUE parameterValues)
163
163
  VALUE* argv;
164
164
  int paramCount = 0, i;
165
165
  ffi_status ffiStatus;
166
- #ifndef HAVE_RUBY_THREAD_HAS_GVL_P
166
+ VALUE exc;
167
167
  rbffi_thread_t oldThread;
168
- #endif
168
+
169
169
  Check_Type(parameterTypes, T_ARRAY);
170
170
  Check_Type(parameterValues, T_ARRAY);
171
171
 
@@ -239,17 +239,17 @@ variadic_invoke(VALUE self, VALUE parameterTypes, VALUE parameterValues)
239
239
 
240
240
  rbffi_SetupCallParams(paramCount, argv, -1, paramTypes, params,
241
241
  ffiValues, NULL, 0, invoker->rbEnums);
242
- #ifndef HAVE_RUBY_THREAD_HAS_GVL_P
243
242
  oldThread = rbffi_active_thread;
244
243
  rbffi_active_thread = rbffi_thread_self();
245
- #endif
246
244
 
247
245
  ffi_call(&cif, FFI_FN(invoker->function), retval, ffiValues);
248
246
 
249
- #ifndef HAVE_RUBY_THREAD_HAS_GVL_P
247
+ exc = rbffi_active_thread.exc;
250
248
  rbffi_active_thread = oldThread;
251
- #endif
252
-
249
+ if (exc != Qnil) {
250
+ rb_exc_raise(exc);
251
+ }
252
+
253
253
  rbffi_save_errno();
254
254
 
255
255
  return rbffi_NativeValue_ToRuby(invoker->returnType, invoker->rbReturnType, retval);
@@ -24,8 +24,8 @@ if !defined?(RUBY_ENGINE) || RUBY_ENGINE == 'ruby' || RUBY_ENGINE == 'rbx'
24
24
  end
25
25
 
26
26
  have_func('rb_thread_blocking_region')
27
- have_func('ruby_native_thread_p')
28
27
  have_func('rb_thread_call_with_gvl')
28
+ have_func('rb_thread_call_without_gvl')
29
29
  have_func('ffi_prep_cif_var')
30
30
 
31
31
  $defs << "-DHAVE_EXTCONF_H" if $defs.empty? # needed so create_header works
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'ffi'
3
- s.version = '1.3.1'
3
+ s.version = '1.4.0'
4
4
  s.author = 'Wayne Meissner'
5
5
  s.email = 'wmeissner@gmail.com'
6
6
  s.homepage = 'http://wiki.github.com/ffi/ffi'
Binary file
Binary file
@@ -80,14 +80,21 @@ module FFI
80
80
 
81
81
 
82
82
 
83
- LIBPREFIX = IS_WINDOWS ? '' : 'lib'
83
+ LIBPREFIX = case OS
84
+ when /windows/
85
+ ''
86
+ when /cygwin/
87
+ 'cyg'
88
+ else
89
+ 'lib'
90
+ end
84
91
 
85
92
  LIBSUFFIX = case OS
86
93
  when /darwin/
87
94
  'dylib'
88
95
  when /linux|bsd|solaris/
89
96
  'so'
90
- when /windows/
97
+ when /windows|cygwin/
91
98
  'dll'
92
99
  else
93
100
  # Punt and just assume a sane unix (i.e. anything but AIX)
@@ -98,6 +105,8 @@ module FFI
98
105
  RbConfig::CONFIG['RUBY_SO_NAME'].split('-')[-2] + '.dll'
99
106
  elsif IS_GNU
100
107
  GNU_LIBC
108
+ elsif OS == 'cygwin'
109
+ "cygwin1.dll"
101
110
  else
102
111
  "#{LIBPREFIX}c.#{LIBSUFFIX}"
103
112
  end
@@ -0,0 +1,3 @@
1
+ rbx.platform.typedef.size_t = uint
2
+ rbx.platform.typedef.ptrdiff_t = int
3
+ rbx.platform.typedef.ssize_t = int
@@ -239,3 +239,13 @@ describe "Buffer#size" do
239
239
  buf.size.should == 14
240
240
  end
241
241
  end
242
+
243
+ describe "Buffer#initialize" do
244
+ it "with block should execute block" do
245
+ block_executed = false
246
+ FFI::Buffer.new(:pointer) do |ptr|
247
+ block_executed = true
248
+ end
249
+ block_executed.should be_true
250
+ end
251
+ end
@@ -89,6 +89,14 @@ describe "Library" do
89
89
  end.getpid.should == Process.pid
90
90
  }.should raise_error(LoadError)
91
91
  end
92
+ it "attach_function :bool_return_true from [ File.expand_path(#{TestLibrary::PATH.inspect}) ]" do
93
+ Module.new do |m|
94
+ m.extend FFI::Library
95
+ ffi_lib File.expand_path(TestLibrary::PATH)
96
+ attach_function :bool_return_true, [ ], :bool
97
+ m.bool_return_true.should == true
98
+ end
99
+ end
92
100
  end
93
101
 
94
102
  def gvar_lib(name, type)
@@ -112,4 +112,12 @@ describe "MemoryPointer" do
112
112
  m.write_long(0x12345678)
113
113
  m.read_pointer.null?.should == false
114
114
  end
115
+
116
+ it "initialize with block should execute block" do
117
+ block_executed = false
118
+ FFI::MemoryPointer.new(:pointer) do |ptr|
119
+ block_executed = true
120
+ end
121
+ block_executed.should be_true
122
+ end
115
123
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ffi
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 7
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
- - 3
9
- - 1
10
- version: 1.3.1
8
+ - 4
9
+ - 0
10
+ version: 1.4.0
11
11
  platform: x86-mingw32
12
12
  authors:
13
13
  - Wayne Meissner
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2013-01-10 00:00:00 Z
18
+ date: 2013-02-21 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  prerelease: false
@@ -417,6 +417,7 @@ files:
417
417
  - lib/ffi/managedstruct.rb
418
418
  - lib/ffi/memorypointer.rb
419
419
  - lib/ffi/platform/arm-linux/types.conf
420
+ - lib/ffi/platform/i386-cygwin/types.conf
420
421
  - lib/ffi/platform/i386-darwin/types.conf
421
422
  - lib/ffi/platform/i386-freebsd/types.conf
422
423
  - lib/ffi/platform/i386-linux/types.conf
@@ -455,7 +456,6 @@ files:
455
456
  - lib/ffi/union.rb
456
457
  - lib/ffi/variadic.rb
457
458
  - lib/ffi.rb
458
- - lib/Lib.iml
459
459
  - spec/ffi/async_callback_spec.rb
460
460
  - spec/ffi/bool_spec.rb
461
461
  - spec/ffi/buffer_spec.rb
@@ -1,21 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <module type="RUBY_MODULE" version="4">
3
- <component name="FacetManager">
4
- <facet type="gem" name="Gem">
5
- <configuration>
6
- <option name="GEM_APP_ROOT_PATH" value="" />
7
- <option name="GEM_APP_TEST_PATH" value="" />
8
- <option name="GEM_APP_LIB_PATH" value="" />
9
- </configuration>
10
- </facet>
11
- </component>
12
- <component name="NewModuleRootManager" inherit-compiler-output="true">
13
- <exclude-output />
14
- <content url="file://$MODULE_DIR$">
15
- <sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
16
- </content>
17
- <orderEntry type="inheritedJdk" />
18
- <orderEntry type="sourceFolder" forTests="false" />
19
- </component>
20
- </module>
21
-