ffi 1.0.2 → 1.0.3

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.

@@ -1,28 +1,20 @@
1
1
  /*
2
- * Copyright (c) 2009, Wayne Meissner
2
+ * Copyright (c) 2009, 2010 Wayne Meissner
3
3
  * All rights reserved.
4
4
  *
5
- * Redistribution and use in source and binary forms, with or without
6
- * modification, are permitted provided that the following conditions are met:
5
+ * This file is part of ruby-ffi.
7
6
  *
8
- * * Redistributions of source code must retain the above copyright notice, this
9
- * list of conditions and the following disclaimer.
10
- * * Redistributions in binary form must reproduce the above copyright notice
11
- * this list of conditions and the following disclaimer in the documentation
12
- * and/or other materials provided with the distribution.
13
- * * The name of the author or authors may not be used to endorse or promote
14
- * products derived from this software without specific prior written permission.
7
+ * This code is free software: you can redistribute it and/or modify it under
8
+ * the terms of the GNU Lesser General Public License version 3 only, as
9
+ * published by the Free Software Foundation.
15
10
  *
16
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
11
+ * This code is distributed in the hope that it will be useful, but WITHOUT
12
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
14
+ * version 3 for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public License
17
+ * version 3 along with this work. If not, see <http://www.gnu.org/licenses/>.
26
18
  */
27
19
 
28
20
  #include <sys/param.h>
@@ -57,10 +49,6 @@
57
49
 
58
50
  #define MAX_METHOD_FIXED_ARITY (6)
59
51
 
60
- #if defined(HAVE_NATIVETHREAD) && !defined(_WIN32) && !defined(__WIN32__)
61
- # define USE_PTHREAD_LOCAL
62
- #endif
63
-
64
52
  #ifndef roundup
65
53
  # define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
66
54
  #endif
@@ -162,13 +162,19 @@ ptr_slice(VALUE self, VALUE rbOffset, VALUE rbLength)
162
162
  static VALUE
163
163
  ptr_inspect(VALUE self)
164
164
  {
165
+ char buf[100];
165
166
  Pointer* ptr;
166
167
 
167
168
  Data_Get_Struct(self, Pointer, ptr);
168
169
 
169
- return ptr->memory.size != LONG_MAX
170
- ? rb_sprintf("#<%s address=%p size=%lu>", rb_obj_classname(self), ptr->memory.address, ptr->memory.size)
171
- : rb_sprintf("#<%s address=%p>", rb_obj_classname(self), ptr->memory.address);
170
+ if (ptr->memory.size != LONG_MAX) {
171
+ snprintf(buf, sizeof(buf), "#<%s address=%p size=%lu>",
172
+ rb_obj_classname(self), ptr->memory.address, ptr->memory.size);
173
+ } else {
174
+ snprintf(buf, sizeof(buf), "#<%s address=%p>", rb_obj_classname(self), ptr->memory.address);
175
+ }
176
+
177
+ return rb_str_new2(buf);
172
178
  }
173
179
 
174
180
  static VALUE
@@ -0,0 +1,169 @@
1
+ /*
2
+ * Copyright (c) 2010 Wayne Meissner
3
+ *
4
+ * All rights reserved.
5
+ *
6
+ * This file is part of ruby-ffi.
7
+ *
8
+ * This code is free software: you can redistribute it and/or modify it under
9
+ * the terms of the GNU Lesser General Public License version 3 only, as
10
+ * published by the Free Software Foundation.
11
+ *
12
+ * This code is distributed in the hope that it will be useful, but WITHOUT
13
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
15
+ * version 3 for more details.
16
+ *
17
+ * You should have received a copy of the GNU Lesser General Public License
18
+ * version 3 along with this work. If not, see <http://www.gnu.org/licenses/>.
19
+ */
20
+
21
+ #include <stdbool.h>
22
+
23
+ #ifndef _WIN32
24
+ # include <pthread.h>
25
+ # include <errno.h>
26
+ #endif
27
+ #include <fcntl.h>
28
+ #include "Thread.h"
29
+
30
+
31
+ #ifndef HAVE_RUBY_THREAD_HAS_GVL_P
32
+ rbffi_thread_t rbffi_active_thread;
33
+
34
+ rbffi_thread_t
35
+ rbffi_thread_self()
36
+ {
37
+ rbffi_thread_t self;
38
+ self.id = pthread_self();
39
+ self.valid = true;
40
+
41
+ return self;
42
+ }
43
+
44
+ bool
45
+ rbffi_thread_equal(rbffi_thread_t* lhs, rbffi_thread_t* rhs)
46
+ {
47
+ return lhs->valid && rhs->valid && pthread_equal(lhs->id, rhs->id);
48
+ }
49
+
50
+ bool
51
+ rbffi_thread_has_gvl_p(void)
52
+ {
53
+ return rbffi_active_thread.valid && pthread_equal(rbffi_active_thread.id, pthread_self());
54
+ }
55
+ #endif // HAVE_RUBY_THREAD_HAS_GVL_P
56
+
57
+ #ifndef HAVE_RB_THREAD_BLOCKING_REGION
58
+ struct BlockingThread {
59
+ pthread_t tid;
60
+ VALUE (*fn)(void *);
61
+ void *data;
62
+ void (*ubf)(void *);
63
+ void *data2;
64
+ VALUE retval;
65
+ int wrfd;
66
+ int rdfd;
67
+ };
68
+
69
+ typedef struct BlockingCall_ {
70
+ void* function;
71
+ void* info;
72
+ void **ffiValues;
73
+ void* retval;
74
+ } BlockingCall;
75
+
76
+ static void*
77
+ rbffi_blocking_thread(void* args)
78
+ {
79
+ struct BlockingThread* thr = (struct BlockingThread *) args;
80
+ char c = 1;
81
+ VALUE retval;
82
+
83
+ retval = (*thr->fn)(thr->data);
84
+
85
+ pthread_testcancel();
86
+
87
+ thr->retval = retval;
88
+
89
+ write(thr->wrfd, &c, sizeof(c));
90
+
91
+ return NULL;
92
+ }
93
+
94
+ static VALUE
95
+ wait_for_thread(void *data)
96
+ {
97
+ struct BlockingThread* thr = (struct BlockingThread *) data;
98
+ char c;
99
+
100
+ if (read(thr->rdfd, &c, 1) < 1) {
101
+ rb_thread_wait_fd(thr->rdfd);
102
+ while (read(thr->rdfd, &c, 1) < 1 && rb_io_wait_readable(thr->rdfd) == Qtrue) {
103
+ ;
104
+ }
105
+ }
106
+
107
+ return Qnil;
108
+ }
109
+
110
+ static VALUE
111
+ cleanup_blocking_thread(void *data, VALUE exc)
112
+ {
113
+ struct BlockingThread* thr = (struct BlockingThread *) data;
114
+
115
+ if (thr->ubf != (void (*)(void *)) -1) {
116
+ (*thr->ubf)(thr->data2);
117
+ } else {
118
+ pthread_kill(thr->tid, SIGVTALRM);
119
+ }
120
+
121
+ return exc;
122
+ }
123
+
124
+ VALUE
125
+ rbffi_thread_blocking_region(VALUE (*func)(void *), void *data1, void (*ubf)(void *), void *data2)
126
+ {
127
+ struct BlockingThread* thr;
128
+ int fd[2];
129
+ VALUE exc;
130
+
131
+ if (pipe(fd) < 0) {
132
+ rb_raise(rb_eSystemCallError, "pipe(2) failed");
133
+ return Qnil;
134
+ }
135
+ fcntl(fd[0], F_SETFL, fcntl(fd[0], F_GETFL) | O_NONBLOCK);
136
+
137
+ thr = ALLOC_N(struct BlockingThread, 1);
138
+ thr->rdfd = fd[0];
139
+ thr->wrfd = fd[1];
140
+ thr->fn = func;
141
+ thr->data = data1;
142
+ thr->ubf = ubf;
143
+ thr->data2 = data2;
144
+ thr->retval = Qnil;
145
+
146
+ if (pthread_create(&thr->tid, NULL, rbffi_blocking_thread, thr) != 0) {
147
+ close(fd[0]);
148
+ close(fd[1]);
149
+ xfree(thr);
150
+ rb_raise(rb_eSystemCallError, "pipe(2) failed");
151
+ return Qnil;
152
+ }
153
+
154
+ exc = rb_rescue2(wait_for_thread, (VALUE) thr, cleanup_blocking_thread, (VALUE) thr,
155
+ rb_eException);
156
+
157
+ pthread_join(thr->tid, NULL);
158
+ close(fd[1]);
159
+ close(fd[0]);
160
+ xfree(thr);
161
+
162
+ if (exc != Qnil) {
163
+ rb_exc_raise(exc);
164
+ }
165
+
166
+ return thr->retval;
167
+ }
168
+
169
+ #endif // HAVE_RB_THREAD_BLOCKING_REGION
@@ -0,0 +1,64 @@
1
+ /*
2
+ * Copyright (c) 2010 Wayne Meissner
3
+ *
4
+ * All rights reserved.
5
+ *
6
+ * This file is part of ruby-ffi.
7
+ *
8
+ * This code is free software: you can redistribute it and/or modify it under
9
+ * the terms of the GNU Lesser General Public License version 3 only, as
10
+ * published by the Free Software Foundation.
11
+ *
12
+ * This code is distributed in the hope that it will be useful, but WITHOUT
13
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
15
+ * version 3 for more details.
16
+ *
17
+ * You should have received a copy of the GNU Lesser General Public License
18
+ * version 3 along with this work. If not, see <http://www.gnu.org/licenses/>.
19
+ */
20
+
21
+ #ifndef THREAD_H
22
+ #define THREAD_H
23
+
24
+ #include <stdbool.h>
25
+ #include <ruby.h>
26
+ #include "extconf.h"
27
+
28
+ #ifdef __cplusplus
29
+ extern "C" {
30
+ #endif
31
+
32
+
33
+ #ifdef HAVE_RUBY_THREAD_HAS_GVL_P
34
+ # define rbffi_thread_has_gvl_p ruby_thread_has_gvl_p
35
+ #else
36
+
37
+ #include <pthread.h>
38
+
39
+ typedef struct {
40
+ pthread_t id;
41
+ bool valid;
42
+ } rbffi_thread_t;
43
+
44
+ extern rbffi_thread_t rbffi_active_thread;
45
+ rbffi_thread_t rbffi_thread_self();
46
+ bool rbffi_thread_equal(rbffi_thread_t* lhs, rbffi_thread_t* rhs);
47
+ bool rbffi_thread_has_gvl_p(void);
48
+
49
+ #endif
50
+ #ifdef HAVE_RB_THREAD_BLOCKING_REGION
51
+ # define rbffi_thread_blocking_region rb_thread_blocking_region
52
+ #else
53
+
54
+ VALUE rbffi_thread_blocking_region(VALUE (*func)(void *), void *data1, void (*ubf)(void *), void *data2);
55
+
56
+ #endif
57
+
58
+
59
+ #ifdef __cplusplus
60
+ }
61
+ #endif
62
+
63
+ #endif /* THREAD_H */
64
+
@@ -95,12 +95,15 @@ type_alignment(VALUE self)
95
95
  static VALUE
96
96
  type_inspect(VALUE self)
97
97
  {
98
+ char buf[100];
98
99
  Type *type;
99
100
 
100
101
  Data_Get_Struct(self, Type, type);
101
102
 
102
- return rb_sprintf("#<%s:%p size=%d alignment=%d>",
103
+ snprintf(buf, sizeof(buf), "#<%s:%p size=%d alignment=%d>",
103
104
  rb_obj_classname(self), type, (int) type->ffiType->size, (int) type->ffiType->alignment);
105
+
106
+ return rb_str_new2(buf);
104
107
  }
105
108
 
106
109
  static VALUE
@@ -128,11 +131,14 @@ builtin_type_free(BuiltinType *type)
128
131
  static VALUE
129
132
  builtin_type_inspect(VALUE self)
130
133
  {
134
+ char buf[100];
131
135
  BuiltinType *type;
132
136
 
133
137
  Data_Get_Struct(self, BuiltinType, type);
134
- return rb_sprintf("#<%s:%s size=%d alignment=%d>",
138
+ snprintf(buf, sizeof(buf), "#<%s:%s size=%d alignment=%d>",
135
139
  rb_obj_classname(self), type->name, (int) type->type.ffiType->size, type->type.ffiType->alignment);
140
+
141
+ return rb_str_new2(buf);
136
142
  }
137
143
 
138
144
  int
@@ -41,7 +41,7 @@ static ID id_from_native = 0;
41
41
 
42
42
 
43
43
  VALUE
44
- rbffi_NativeValue_ToRuby(Type* type, VALUE rbType, const void* ptr, VALUE enums)
44
+ rbffi_NativeValue_ToRuby(Type* type, VALUE rbType, const void* ptr)
45
45
  {
46
46
  switch (type->nativeType) {
47
47
  case NATIVE_VOID:
@@ -100,11 +100,10 @@ rbffi_NativeValue_ToRuby(Type* type, VALUE rbType, const void* ptr, VALUE enums)
100
100
  case NATIVE_MAPPED: {
101
101
  // For mapped types, first convert to the real native type, then upcall to
102
102
  // ruby to convert to the expected return type
103
- MappedType* m;
103
+ MappedType* m = (MappedType *) type;
104
104
  VALUE values[2];
105
105
 
106
- Data_Get_Struct(rbType, MappedType, m);
107
- values[0] = rbffi_NativeValue_ToRuby(m->type, m->rbType, ptr, enums);
106
+ values[0] = rbffi_NativeValue_ToRuby(m->type, m->rbType, ptr);
108
107
  values[1] = Qnil;
109
108
 
110
109
  return rb_funcall2(m->rbConverter, id_from_native, 2, values);
@@ -76,7 +76,7 @@ typedef enum {
76
76
  #include <ffi.h>
77
77
  #include "Type.h"
78
78
 
79
- VALUE rbffi_NativeValue_ToRuby(Type* type, VALUE rbType, const void* ptr, VALUE enums);
79
+ VALUE rbffi_NativeValue_ToRuby(Type* type, VALUE rbType, const void* ptr);
80
80
  void rbffi_Types_Init(VALUE moduleFFI);
81
81
 
82
82
  #ifdef __cplusplus
@@ -1,28 +1,20 @@
1
1
  /*
2
- * Copyright (c) 2008, 2009, Wayne Meissner
2
+ * Copyright (c) 2008-2010 Wayne Meissner
3
3
  * All rights reserved.
4
4
  *
5
- * Redistribution and use in source and binary forms, with or without
6
- * modification, are permitted provided that the following conditions are met:
5
+ * This file is part of ruby-ffi.
7
6
  *
8
- * * Redistributions of source code must retain the above copyright notice, this
9
- * list of conditions and the following disclaimer.
10
- * * Redistributions in binary form must reproduce the above copyright notice
11
- * this list of conditions and the following disclaimer in the documentation
12
- * and/or other materials provided with the distribution.
13
- * * The name of the author or authors may not be used to endorse or promote
14
- * products derived from this software without specific prior written permission.
7
+ * This code is free software: you can redistribute it and/or modify it under
8
+ * the terms of the GNU Lesser General Public License version 3 only, as
9
+ * published by the Free Software Foundation.
15
10
  *
16
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
11
+ * This code is distributed in the hope that it will be useful, but WITHOUT
12
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
14
+ * version 3 for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public License
17
+ * version 3 along with this work. If not, see <http://www.gnu.org/licenses/>.
26
18
  */
27
19
 
28
20
  #include <sys/param.h>
@@ -44,6 +36,7 @@
44
36
  #include "LastError.h"
45
37
  #include "MethodHandle.h"
46
38
  #include "Call.h"
39
+ #include "Thread.h"
47
40
 
48
41
  typedef struct VariadicInvoker_ {
49
42
  VALUE rbAddress;
@@ -159,7 +152,9 @@ variadic_invoke(VALUE self, VALUE parameterTypes, VALUE parameterValues)
159
152
  VALUE* argv;
160
153
  int paramCount = 0, i;
161
154
  ffi_status ffiStatus;
162
-
155
+ #ifndef HAVE_RUBY_THREAD_HAS_GVL_P
156
+ rbffi_thread_t oldThread;
157
+ #endif
163
158
  Check_Type(parameterTypes, T_ARRAY);
164
159
  Check_Type(parameterValues, T_ARRAY);
165
160
 
@@ -229,12 +224,20 @@ variadic_invoke(VALUE self, VALUE parameterTypes, VALUE parameterValues)
229
224
 
230
225
  rbffi_SetupCallParams(paramCount, argv, -1, paramTypes, params,
231
226
  ffiValues, NULL, 0, invoker->rbEnums);
227
+ #ifndef HAVE_RUBY_THREAD_HAS_GVL_P
228
+ oldThread = rbffi_active_thread;
229
+ rbffi_active_thread = rbffi_thread_self();
230
+ #endif
232
231
 
233
232
  ffi_call(&cif, invoker->function, retval, ffiValues);
234
233
 
234
+ #ifndef HAVE_RUBY_THREAD_HAS_GVL_P
235
+ rbffi_active_thread = oldThread;
236
+ #endif
237
+
235
238
  rbffi_save_errno();
236
239
 
237
- return rbffi_NativeValue_ToRuby(invoker->returnType, invoker->rbReturnType, retval, invoker->rbEnums);
240
+ return rbffi_NativeValue_ToRuby(invoker->returnType, invoker->rbReturnType, retval);
238
241
  }
239
242
 
240
243