ffi 1.0.0 → 1.0.1
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/Rakefile +4 -2
- data/ext/ffi_c/AbstractMemory.c +59 -12
- data/ext/ffi_c/Function.c +67 -4
- metadata +7 -5
data/Rakefile
CHANGED
@@ -5,7 +5,7 @@ USE_RAKE_COMPILER = (RUBY_PLATFORM =~ /java/) ? false : true
|
|
5
5
|
if USE_RAKE_COMPILER
|
6
6
|
gem 'rake-compiler', '>=0.6.0'
|
7
7
|
require 'rake/extensiontask'
|
8
|
-
ENV['RUBY_CC_VERSION'] = '1.
|
8
|
+
ENV['RUBY_CC_VERSION'] = '1.9.2'
|
9
9
|
end
|
10
10
|
|
11
11
|
require 'date'
|
@@ -75,7 +75,7 @@ PROJ.name = 'ffi'
|
|
75
75
|
PROJ.authors = 'Wayne Meissner'
|
76
76
|
PROJ.email = 'wmeissner@gmail.com'
|
77
77
|
PROJ.url = 'http://wiki.github.com/ffi/ffi'
|
78
|
-
PROJ.version = '1.0.
|
78
|
+
PROJ.version = '1.0.1'
|
79
79
|
PROJ.rubyforge.name = 'ffi'
|
80
80
|
PROJ.readme_file = 'README.rdoc'
|
81
81
|
|
@@ -90,9 +90,11 @@ PROJ.ann.email[:server] = 'smtp.gmail.com'
|
|
90
90
|
PROJ.gem.need_tar = false
|
91
91
|
PROJ.gem.files = %w(History.txt LICENSE README.rdoc Rakefile) + Dir.glob("{ext,gen,lib,spec,tasks}/**/*")
|
92
92
|
PROJ.gem.platform = Gem::Platform::RUBY
|
93
|
+
PROJ.gem.required_ruby_version = ">= 1.9.2"
|
93
94
|
|
94
95
|
# Override Mr. Bones autogenerated extensions and force ours in
|
95
96
|
PROJ.gem.extras['extensions'] = %w(ext/ffi_c/extconf.rb gen/Rakefile)
|
97
|
+
PROJ.gem.extras['required_ruby_version'] = ">= 1.9.2"
|
96
98
|
|
97
99
|
# RDoc
|
98
100
|
PROJ.rdoc.exclude << '^ext\/'
|
data/ext/ffi_c/AbstractMemory.c
CHANGED
@@ -137,25 +137,72 @@ SWAPU16(uint16_t x)
|
|
137
137
|
}
|
138
138
|
|
139
139
|
#define SWAP16(x) (x)
|
140
|
-
#
|
141
|
-
#define
|
140
|
+
#if __GNUC__ < 4
|
141
|
+
#define bswap32(x) \
|
142
|
+
(((x << 24) & 0xff000000) | \
|
143
|
+
((x << 8) & 0x00ff0000) | \
|
144
|
+
((x >> 8) & 0x0000ff00) | \
|
145
|
+
((x >> 24) & 0x000000ff))
|
146
|
+
|
147
|
+
#define bswap64(x) \
|
148
|
+
(((x << 56) & 0xff00000000000000ULL) | \
|
149
|
+
((x << 40) & 0x00ff000000000000ULL) | \
|
150
|
+
((x << 24) & 0x0000ff0000000000ULL) | \
|
151
|
+
((x << 8) & 0x000000ff00000000ULL) | \
|
152
|
+
((x >> 8) & 0x00000000ff000000ULL) | \
|
153
|
+
((x >> 24) & 0x0000000000ff0000ULL) | \
|
154
|
+
((x >> 40) & 0x000000000000ff00ULL) | \
|
155
|
+
((x >> 56) & 0x00000000000000ffULL))
|
156
|
+
|
157
|
+
static inline int32_t
|
158
|
+
SWAPS32(int32_t x)
|
159
|
+
{
|
160
|
+
return bswap32(x);
|
161
|
+
}
|
162
|
+
|
163
|
+
static inline uint32_t
|
164
|
+
SWAPU32(uint32_t x)
|
165
|
+
{
|
166
|
+
return bswap32(x);
|
167
|
+
}
|
168
|
+
|
169
|
+
static inline int64_t
|
170
|
+
SWAPS64(int64_t x)
|
171
|
+
{
|
172
|
+
return bswap64(x);
|
173
|
+
}
|
174
|
+
|
175
|
+
static inline uint64_t
|
176
|
+
SWAPU64(uint64_t x)
|
177
|
+
{
|
178
|
+
return bswap64(x);
|
179
|
+
}
|
180
|
+
|
181
|
+
#else
|
182
|
+
# define SWAPU32(x) __builtin_bswap32(x)
|
183
|
+
# define SWAPS32(x) __builtin_bswap32(x)
|
184
|
+
# define SWAPS64(x) __builtin_bswap64(x)
|
185
|
+
# define SWAPU64(x) __builtin_bswap64(x)
|
186
|
+
#endif
|
142
187
|
|
143
188
|
#if LONG_MAX > INT_MAX
|
144
|
-
# define
|
189
|
+
# define SWAPSLONG SWAPS64
|
190
|
+
# define SWAPULONG SWAPU64
|
145
191
|
#else
|
146
|
-
# define
|
192
|
+
# define SWAPSLONG SWAPS32
|
193
|
+
# define SWAPULONG SWAPU32
|
147
194
|
#endif
|
148
195
|
|
149
196
|
NUM_OP(int8, int8_t, NUM2INT, INT2NUM, NOSWAP);
|
150
197
|
NUM_OP(uint8, uint8_t, NUM2UINT, UINT2NUM, NOSWAP);
|
151
|
-
NUM_OP(int16, int16_t, NUM2INT, INT2NUM,
|
152
|
-
NUM_OP(uint16, uint16_t, NUM2UINT, UINT2NUM,
|
153
|
-
NUM_OP(int32, int32_t, NUM2INT, INT2NUM,
|
154
|
-
NUM_OP(uint32, uint32_t, NUM2UINT, UINT2NUM,
|
155
|
-
NUM_OP(int64, int64_t, NUM2LL, LL2NUM,
|
156
|
-
NUM_OP(uint64, uint64_t, NUM2ULL, ULL2NUM,
|
157
|
-
NUM_OP(long, long, NUM2LONG, LONG2NUM,
|
158
|
-
NUM_OP(ulong, unsigned long, NUM2ULONG, ULONG2NUM,
|
198
|
+
NUM_OP(int16, int16_t, NUM2INT, INT2NUM, SWAPS16);
|
199
|
+
NUM_OP(uint16, uint16_t, NUM2UINT, UINT2NUM, SWAPU16);
|
200
|
+
NUM_OP(int32, int32_t, NUM2INT, INT2NUM, SWAPS32);
|
201
|
+
NUM_OP(uint32, uint32_t, NUM2UINT, UINT2NUM, SWAPU32);
|
202
|
+
NUM_OP(int64, int64_t, NUM2LL, LL2NUM, SWAPS64);
|
203
|
+
NUM_OP(uint64, uint64_t, NUM2ULL, ULL2NUM, SWAPU64);
|
204
|
+
NUM_OP(long, long, NUM2LONG, LONG2NUM, SWAPSLONG);
|
205
|
+
NUM_OP(ulong, unsigned long, NUM2ULONG, ULONG2NUM, SWAPULONG);
|
159
206
|
NUM_OP(float32, float, NUM2DBL, rb_float_new, NOSWAP);
|
160
207
|
NUM_OP(float64, double, NUM2DBL, rb_float_new, NOSWAP);
|
161
208
|
|
data/ext/ffi_c/Function.c
CHANGED
@@ -76,10 +76,6 @@ static VALUE async_cb_event(void);
|
|
76
76
|
static VALUE async_cb_call(void *);
|
77
77
|
#endif
|
78
78
|
|
79
|
-
#if defined(HAVE_NATIVETHREAD) && defined (HAVE_RB_THREAD_BLOCKING_REGION)
|
80
|
-
# define DEFER_ASYNC_CALLBACK
|
81
|
-
#endif
|
82
|
-
|
83
79
|
#ifdef HAVE_RUBY_THREAD_HAS_GVL_P
|
84
80
|
extern int ruby_thread_has_gvl_p(void);
|
85
81
|
#endif
|
@@ -106,6 +102,8 @@ struct gvl_callback {
|
|
106
102
|
# ifndef _WIN32
|
107
103
|
pthread_cond_t async_cond;
|
108
104
|
pthread_mutex_t async_mutex;
|
105
|
+
# else
|
106
|
+
HANDLE async_event;
|
109
107
|
# endif
|
110
108
|
#endif
|
111
109
|
};
|
@@ -116,6 +114,9 @@ static struct gvl_callback* async_cb_list = NULL;
|
|
116
114
|
# ifndef _WIN32
|
117
115
|
static pthread_mutex_t async_cb_mutex = PTHREAD_MUTEX_INITIALIZER;
|
118
116
|
static pthread_cond_t async_cb_cond = PTHREAD_COND_INITIALIZER;
|
117
|
+
# else
|
118
|
+
static HANDLE async_cb_cond;
|
119
|
+
static CRITICAL_SECTION async_cb_lock;
|
119
120
|
# endif
|
120
121
|
#endif
|
121
122
|
|
@@ -407,6 +408,21 @@ callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data)
|
|
407
408
|
|
408
409
|
// Wait for the thread executing the ruby callback to signal it is done
|
409
410
|
pthread_cond_wait(&cb.async_cond, &cb.async_mutex);
|
411
|
+
#elif defined(DEFER_ASYNC_CALLBACK) && !defined(_WIN32)
|
412
|
+
} else {
|
413
|
+
cb.async_event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
414
|
+
|
415
|
+
// Now signal the async callback thread
|
416
|
+
EnterCriticalSection(&async_cb_lock);
|
417
|
+
cb.next = async_cb_list;
|
418
|
+
async_cb_list = &cb;
|
419
|
+
LeaveCriticalSection(&async_cb_lock);
|
420
|
+
|
421
|
+
SetEvent(async_cb_cond);
|
422
|
+
|
423
|
+
// Wait for the thread executing the ruby callback to signal it is done
|
424
|
+
WaitForSingleObject(cb.async_event, INFINITE);
|
425
|
+
CloseHandle(cb.async_event);
|
410
426
|
#endif
|
411
427
|
}
|
412
428
|
}
|
@@ -437,6 +453,44 @@ async_cb_event(void)
|
|
437
453
|
return Qnil;
|
438
454
|
}
|
439
455
|
|
456
|
+
#ifdef _WIN32
|
457
|
+
static VALUE
|
458
|
+
async_cb_wait(void *data)
|
459
|
+
{
|
460
|
+
struct async_wait* w = (struct async_wait *) data;
|
461
|
+
|
462
|
+
w->cb = NULL;
|
463
|
+
|
464
|
+
EnterCriticalSection(&async_cb_lock);
|
465
|
+
|
466
|
+
while (!w->stop && async_cb_list == NULL) {
|
467
|
+
LeaveCriticalSection(&async_cb_lock);
|
468
|
+
WaitForSingleObject(async_cb_cond, INFINITE);
|
469
|
+
EnterCriticalSection(&async_cb_lock);
|
470
|
+
}
|
471
|
+
|
472
|
+
if (async_cb_list != NULL) {
|
473
|
+
w->cb = async_cb_list;
|
474
|
+
async_cb_list = async_cb_list->next;
|
475
|
+
}
|
476
|
+
|
477
|
+
LeaveCriticalSection(&async_cb_lock);
|
478
|
+
|
479
|
+
return Qnil;
|
480
|
+
}
|
481
|
+
|
482
|
+
static void
|
483
|
+
async_cb_stop(void *data)
|
484
|
+
{
|
485
|
+
struct async_wait* w = (struct async_wait *) data;
|
486
|
+
|
487
|
+
EnterCriticalSection(&async_cb_lock);
|
488
|
+
w->stop = true;
|
489
|
+
LeaveCriticalSection(&async_cb_lock);
|
490
|
+
SetEvent(async_cb_cond);
|
491
|
+
}
|
492
|
+
|
493
|
+
#else
|
440
494
|
static VALUE
|
441
495
|
async_cb_wait(void *data)
|
442
496
|
{
|
@@ -470,6 +524,7 @@ async_cb_stop(void *data)
|
|
470
524
|
pthread_cond_signal(&async_cb_cond);
|
471
525
|
pthread_mutex_unlock(&async_cb_mutex);
|
472
526
|
}
|
527
|
+
#endif
|
473
528
|
|
474
529
|
static VALUE
|
475
530
|
async_cb_call(void *data)
|
@@ -479,9 +534,13 @@ async_cb_call(void *data)
|
|
479
534
|
callback_with_gvl(cb);
|
480
535
|
|
481
536
|
// Signal the original native thread that the ruby code has completed
|
537
|
+
#ifdef _WIN32
|
538
|
+
SetEvent(cb->async_event);
|
539
|
+
#else
|
482
540
|
pthread_mutex_lock(&cb->async_mutex);
|
483
541
|
pthread_cond_signal(&cb->async_cond);
|
484
542
|
pthread_mutex_unlock(&cb->async_mutex);
|
543
|
+
#endif
|
485
544
|
|
486
545
|
return Qnil;
|
487
546
|
}
|
@@ -714,5 +773,9 @@ rbffi_Function_Init(VALUE moduleFFI)
|
|
714
773
|
id_cb_ref = rb_intern("@__ffi_callback__");
|
715
774
|
id_to_native = rb_intern("to_native");
|
716
775
|
id_from_native = rb_intern("from_native");
|
776
|
+
#ifdef _WIN32
|
777
|
+
InitializeCriticalSection(&async_cb_lock);
|
778
|
+
async_cb_cond = CreateEvent(NULL, FALSE, FALSE, NULL);
|
779
|
+
#endif
|
717
780
|
}
|
718
781
|
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 1
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 1.0.
|
8
|
+
- 1
|
9
|
+
version: 1.0.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Wayne Meissner
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-12-03 00:00:00 +10:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -450,8 +450,10 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
450
450
|
- - ">="
|
451
451
|
- !ruby/object:Gem::Version
|
452
452
|
segments:
|
453
|
-
-
|
454
|
-
|
453
|
+
- 1
|
454
|
+
- 9
|
455
|
+
- 2
|
456
|
+
version: 1.9.2
|
455
457
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
456
458
|
none: false
|
457
459
|
requirements:
|