ffi 0.5.4 → 0.6.0

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.

Files changed (203) hide show
  1. data/LICENSE +1 -27
  2. data/Rakefile +2 -11
  3. data/ext/ffi_c/AbstractMemory.c +6 -8
  4. data/ext/ffi_c/AbstractMemory.h +23 -21
  5. data/ext/ffi_c/AutoPointer.c +0 -1
  6. data/ext/ffi_c/Buffer.c +23 -8
  7. data/ext/ffi_c/Call.c +28 -0
  8. data/ext/ffi_c/Call.h +5 -1
  9. data/ext/ffi_c/DynamicLibrary.c +0 -1
  10. data/ext/ffi_c/Function.c +19 -2
  11. data/ext/ffi_c/MemoryPointer.c +2 -3
  12. data/ext/ffi_c/Pointer.c +23 -9
  13. data/ext/ffi_c/Struct.c +142 -69
  14. data/ext/ffi_c/Struct.h +16 -7
  15. data/ext/ffi_c/StructLayout.c +92 -55
  16. data/ext/ffi_c/Type.c +5 -22
  17. data/ext/ffi_c/Type.h +1 -1
  18. data/ext/ffi_c/Types.c +8 -2
  19. data/ext/ffi_c/Types.h +2 -0
  20. data/ext/ffi_c/extconf.rb +11 -7
  21. data/ext/ffi_c/libffi/ChangeLog +900 -84
  22. data/ext/ffi_c/libffi/ChangeLog.libffi +311 -0
  23. data/ext/ffi_c/libffi/LICENSE +1 -1
  24. data/ext/ffi_c/libffi/Makefile.am +14 -4
  25. data/ext/ffi_c/libffi/Makefile.in +362 -211
  26. data/ext/ffi_c/libffi/README +70 -92
  27. data/ext/ffi_c/libffi/aclocal.m4 +6068 -4586
  28. data/ext/ffi_c/libffi/config.guess +125 -143
  29. data/ext/ffi_c/libffi/config.sub +103 -27
  30. data/ext/ffi_c/libffi/configure +11364 -18497
  31. data/ext/ffi_c/libffi/configure.ac +43 -4
  32. data/ext/ffi_c/libffi/doc/libffi.info +15 -15
  33. data/ext/ffi_c/libffi/doc/libffi.texi +1 -1
  34. data/ext/ffi_c/libffi/doc/stamp-vti +4 -4
  35. data/ext/ffi_c/libffi/doc/version.texi +4 -4
  36. data/ext/ffi_c/libffi/fficonfig.h.in +24 -3
  37. data/ext/ffi_c/libffi/include/Makefile.am +1 -1
  38. data/ext/ffi_c/libffi/include/Makefile.in +97 -50
  39. data/ext/ffi_c/libffi/include/ffi.h.in +8 -2
  40. data/ext/ffi_c/libffi/include/ffi_common.h +24 -0
  41. data/ext/ffi_c/libffi/libtool-version +1 -1
  42. data/ext/ffi_c/libffi/ltmain.sh +7346 -5870
  43. data/ext/ffi_c/libffi/m4/libtool.m4 +7360 -0
  44. data/ext/ffi_c/libffi/m4/ltoptions.m4 +368 -0
  45. data/ext/ffi_c/libffi/m4/ltsugar.m4 +123 -0
  46. data/ext/ffi_c/libffi/m4/ltversion.m4 +23 -0
  47. data/ext/ffi_c/libffi/m4/lt~obsolete.m4 +92 -0
  48. data/ext/ffi_c/libffi/man/Makefile.in +115 -62
  49. data/ext/ffi_c/libffi/man/ffi_call.3 +3 -3
  50. data/ext/ffi_c/libffi/missing +15 -8
  51. data/ext/ffi_c/libffi/src/arm/sysv.S +15 -8
  52. data/ext/ffi_c/libffi/src/avr32/ffi.c +421 -0
  53. data/ext/ffi_c/libffi/src/avr32/ffitarget.h +50 -0
  54. data/ext/ffi_c/libffi/src/avr32/sysv.S +208 -0
  55. data/ext/ffi_c/libffi/src/closures.c +47 -10
  56. data/ext/ffi_c/libffi/src/frv/ffi.c +1 -1
  57. data/ext/ffi_c/libffi/src/java_raw_api.c +0 -3
  58. data/ext/ffi_c/libffi/src/mips/ffi.c +135 -32
  59. data/ext/ffi_c/libffi/src/mips/ffitarget.h +37 -4
  60. data/ext/ffi_c/libffi/src/mips/n32.S +67 -10
  61. data/ext/ffi_c/libffi/src/mips/o32.S +8 -8
  62. data/ext/ffi_c/libffi/src/pa/ffi.c +7 -0
  63. data/ext/ffi_c/libffi/src/powerpc/aix.S +163 -64
  64. data/ext/ffi_c/libffi/src/powerpc/aix_closure.S +308 -112
  65. data/ext/ffi_c/libffi/src/powerpc/ffi.c +20 -7
  66. data/ext/ffi_c/libffi/src/powerpc/ffi_darwin.c +208 -80
  67. data/ext/ffi_c/libffi/src/powerpc/ffitarget.h +11 -3
  68. data/ext/ffi_c/libffi/src/powerpc/sysv.S +12 -23
  69. data/ext/ffi_c/libffi/src/s390/sysv.S +1 -1
  70. data/ext/ffi_c/libffi/src/sh/sysv.S +9 -9
  71. data/ext/ffi_c/libffi/src/sh64/ffi.c +37 -22
  72. data/ext/ffi_c/libffi/src/sh64/sysv.S +23 -14
  73. data/ext/ffi_c/libffi/src/sparc/ffi.c +21 -6
  74. data/ext/ffi_c/libffi/src/sparc/v8.S +55 -14
  75. data/ext/ffi_c/libffi/src/x86/darwin.S +10 -9
  76. data/ext/ffi_c/libffi/src/x86/ffi.c +293 -86
  77. data/ext/ffi_c/libffi/src/x86/ffi64.c +73 -19
  78. data/ext/ffi_c/libffi/src/x86/ffitarget.h +30 -0
  79. data/ext/ffi_c/libffi/src/x86/sysv.S +21 -4
  80. data/ext/ffi_c/libffi/src/x86/unix64.S +8 -4
  81. data/ext/ffi_c/libffi/src/x86/win32.S +633 -147
  82. data/ext/ffi_c/libffi/src/x86/win64.S +460 -0
  83. data/ext/ffi_c/libffi/testsuite/Makefile.am +63 -54
  84. data/ext/ffi_c/libffi/testsuite/Makefile.in +112 -77
  85. data/ext/ffi_c/libffi/testsuite/lib/libffi-dg.exp +12 -1
  86. data/ext/ffi_c/libffi/testsuite/libffi.call/call.exp +4 -4
  87. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn0.c +7 -15
  88. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn1.c +7 -15
  89. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn2.c +7 -15
  90. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn3.c +7 -15
  91. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn4.c +7 -15
  92. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn5.c +7 -14
  93. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn6.c +7 -15
  94. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_loc_fn0.c +95 -0
  95. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_stdcall.c +6 -14
  96. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_12byte.c +4 -12
  97. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_16byte.c +4 -12
  98. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_18byte.c +4 -12
  99. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_19byte.c +4 -12
  100. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_1_1byte.c +4 -12
  101. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_20byte.c +4 -12
  102. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_20byte1.c +4 -12
  103. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_24byte.c +4 -12
  104. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_2byte.c +4 -12
  105. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3_1byte.c +4 -12
  106. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3byte1.c +4 -12
  107. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3byte2.c +4 -12
  108. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_4_1byte.c +4 -12
  109. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_4byte.c +4 -12
  110. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_5_1_byte.c +4 -12
  111. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_5byte.c +4 -12
  112. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_64byte.c +4 -12
  113. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_6_1_byte.c +4 -12
  114. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_6byte.c +4 -12
  115. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_7_1_byte.c +4 -12
  116. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_7byte.c +4 -12
  117. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_8byte.c +4 -12
  118. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_9byte1.c +4 -12
  119. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_9byte2.c +4 -12
  120. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_double.c +4 -12
  121. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_float.c +4 -12
  122. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble.c +4 -12
  123. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble_split.c +134 -0
  124. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble_split2.c +117 -0
  125. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_pointer.c +11 -17
  126. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint16.c +4 -12
  127. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint32.c +4 -12
  128. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint64.c +7 -15
  129. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint16.c +4 -12
  130. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint32.c +4 -12
  131. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint64.c +7 -15
  132. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_dbls_struct.c +66 -0
  133. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_double.c +4 -12
  134. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_double_va.c +57 -0
  135. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_float.c +4 -13
  136. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_longdouble.c +105 -0
  137. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_longdouble_va.c +57 -0
  138. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_schar.c +4 -12
  139. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_sshort.c +4 -12
  140. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_sshortchar.c +4 -12
  141. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_uchar.c +4 -12
  142. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_ushort.c +4 -12
  143. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_ushortchar.c +4 -12
  144. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_pointer.c +74 -0
  145. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_pointer_stack.c +140 -0
  146. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_schar.c +4 -12
  147. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_sint.c +4 -12
  148. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_sshort.c +4 -12
  149. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uchar.c +4 -12
  150. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uint.c +4 -12
  151. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ulonglong.c +8 -16
  152. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ushort.c +4 -12
  153. data/ext/ffi_c/libffi/testsuite/libffi.call/err_bad_abi.c +37 -0
  154. data/ext/ffi_c/libffi/testsuite/libffi.call/err_bad_typedef.c +25 -0
  155. data/ext/ffi_c/libffi/testsuite/libffi.call/ffitest.h +31 -0
  156. data/ext/ffi_c/libffi/testsuite/libffi.call/float2.c +2 -1
  157. data/ext/ffi_c/libffi/testsuite/libffi.call/huge_struct.c +342 -0
  158. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct.c +4 -12
  159. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct1.c +4 -12
  160. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct10.c +4 -12
  161. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct2.c +4 -12
  162. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct3.c +4 -12
  163. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct4.c +4 -12
  164. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct5.c +4 -12
  165. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct6.c +4 -12
  166. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct7.c +4 -12
  167. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct8.c +4 -12
  168. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct9.c +4 -12
  169. data/ext/ffi_c/libffi/testsuite/libffi.call/problem1.c +4 -12
  170. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ldl.c +1 -1
  171. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ll1.c +1 -1
  172. data/ext/ffi_c/libffi/testsuite/libffi.call/stret_large.c +145 -0
  173. data/ext/ffi_c/libffi/testsuite/libffi.call/stret_large2.c +148 -0
  174. data/ext/ffi_c/libffi/testsuite/libffi.call/stret_medium.c +124 -0
  175. data/ext/ffi_c/libffi/testsuite/libffi.call/stret_medium2.c +124 -0
  176. data/ext/ffi_c/libffi/testsuite/libffi.call/testclosure.c +70 -0
  177. data/ext/ffi_c/libffi/testsuite/libffi.special/ffitestcxx.h +10 -0
  178. data/ext/ffi_c/libffi/testsuite/libffi.special/special.exp +4 -5
  179. data/ext/ffi_c/libffi/testsuite/libffi.special/unwindtest.cc +17 -16
  180. data/ext/ffi_c/libffi/texinfo.tex +155 -427
  181. data/lib/ffi/autopointer.rb +79 -20
  182. data/lib/ffi/callback.rb +4 -10
  183. data/lib/ffi/enum.rb +28 -0
  184. data/lib/ffi/io.rb +28 -0
  185. data/lib/ffi/library.rb +237 -182
  186. data/lib/ffi/memorypointer.rb +28 -62
  187. data/lib/ffi/platform.rb +27 -0
  188. data/lib/ffi/pointer.rb +28 -0
  189. data/lib/ffi/struct.rb +55 -1
  190. data/lib/ffi/types.rb +29 -0
  191. data/lib/ffi/variadic.rb +29 -0
  192. data/spec/ffi/library_spec.rb +31 -5
  193. data/spec/ffi/rbx/attach_function_spec.rb +2 -1
  194. data/spec/ffi/rbx/memory_pointer_spec.rb +2 -1
  195. data/spec/ffi/spec_helper.rb +5 -1
  196. data/spec/ffi/struct_spec.rb +64 -0
  197. metadata +28 -8
  198. data/ext/ffi_c/libffi/TODO +0 -1
  199. data/ext/ffi_c/libffi/ltcf-c.sh +0 -861
  200. data/ext/ffi_c/libffi/ltcf-cxx.sh +0 -1069
  201. data/ext/ffi_c/libffi/ltcf-gcj.sh +0 -700
  202. data/ext/ffi_c/libffi/ltconfig +0 -2862
  203. data/ext/ffi_c/libffi/mkinstalldirs +0 -158
@@ -1,3 +1,32 @@
1
+ #
2
+ # Copyright (C) 2008, 2009 Wayne Meissner
3
+ # Copyright (C) 2008 Mike Dalessio
4
+ #
5
+ # All rights reserved.
6
+ #
7
+ # Redistribution and use in source and binary forms, with or without
8
+ # modification, are permitted provided that the following conditions are met:
9
+ #
10
+ # * Redistributions of source code must retain the above copyright notice, this
11
+ # list of conditions and the following disclaimer.
12
+ # * Redistributions in binary form must reproduce the above copyright notice
13
+ # this list of conditions and the following disclaimer in the documentation
14
+ # and/or other materials provided with the distribution.
15
+ # * Neither the name of the Evan Phoenix nor the names of its contributors
16
+ # may be used to endorse or promote products derived from this software
17
+ # without specific prior written permission.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
23
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+
1
30
  module FFI
2
31
  class AutoPointer < Pointer
3
32
 
@@ -30,32 +59,62 @@ module FFI
30
59
  def initialize(ptr, proc=nil, &block)
31
60
  raise TypeError, "Invalid pointer" if ptr.nil? || !ptr.kind_of?(Pointer) \
32
61
  || ptr.kind_of?(MemoryPointer) || ptr.kind_of?(AutoPointer)
33
- free_lambda = if proc and proc.is_a? Method
34
- AutoPointer.finalize(ptr, AutoPointer.method_to_proc(proc))
35
- elsif proc and proc.is_a? Proc
36
- AutoPointer.finalize(ptr, proc)
37
- else
38
- AutoPointer.finalize(ptr, AutoPointer.method_to_proc(self.class.method(:release)))
39
- end
62
+
63
+ @releaser = if proc
64
+ raise RuntimeError.new("proc must be callable") unless proc.respond_to?(:call)
65
+ CallableReleaser.new(ptr, proc)
66
+
67
+ else
68
+ raise RuntimeError.new("no release method defined") unless self.class.respond_to?(:release)
69
+ DefaultReleaser.new(ptr, self.class)
70
+ end
71
+
40
72
  self.parent = ptr
41
- ObjectSpace.define_finalizer(self, free_lambda)
73
+ ObjectSpace.define_finalizer(self, @releaser)
42
74
  self
43
75
  end
44
- def self.release(ptr)
76
+
77
+ def free
78
+ @releaser.free
79
+ end
80
+
81
+ def autorelease=(autorelease)
82
+ @releaser.autorelease=(autorelease)
83
+ end
84
+
85
+ class Releaser
86
+ def initialize(ptr, proc)
87
+ @ptr = ptr
88
+ @proc = proc
89
+ @autorelease = true
90
+ end
91
+
92
+ def free
93
+ raise RuntimeError.new("pointer already freed") unless @ptr
94
+ @autorelease = false
95
+ @ptr = nil
96
+ @proc = nil
97
+ end
98
+
99
+ def autorelease=(autorelease)
100
+ raise RuntimeError.new("pointer already freed") unless @ptr
101
+ @autorelease = autorelease
102
+ end
103
+
45
104
  end
46
105
 
47
- private
48
- def self.finalize(ptr, proc)
49
- #
50
- # having a method create the lambda eliminates inadvertent
51
- # references to the underlying object, which would prevent GC
52
- # from running.
53
- #
54
- Proc.new { |*args| proc.call(ptr) }
106
+ class DefaultReleaser < Releaser
107
+ def call(*args)
108
+ @proc.release(@ptr) if @autorelease && @ptr
109
+ end
55
110
  end
56
- def self.method_to_proc method
57
- # again, can't call this inline as it causes a memory leak.
58
- method.to_proc
111
+
112
+ class CallableReleaser < Releaser
113
+ def call(*args)
114
+ @proc.call(@ptr) if @autorelease && @ptr
115
+ end
59
116
  end
117
+
60
118
  end
119
+
61
120
  end
@@ -1,10 +1,4 @@
1
- module FFI
2
- module Library
3
-
4
- end
5
- # class Callback
6
- # def initialize
7
- #
8
- # end
9
- # end
10
- end
1
+ #
2
+ # All the code from this file is now implemented in C. This file remains
3
+ # to satisfy any leftover require 'ffi/callback' in user code
4
+ #
@@ -1,3 +1,31 @@
1
+ #
2
+ # Copyright (C) 2009 Luc Heinrich
3
+ #
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions are met:
8
+ #
9
+ # * Redistributions of source code must retain the above copyright notice, this
10
+ # list of conditions and the following disclaimer.
11
+ # * Redistributions in binary form must reproduce the above copyright notice
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ # * Neither the name of the Evan Phoenix nor the names of its contributors
15
+ # may be used to endorse or promote products derived from this software
16
+ # without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
22
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+
1
29
  module FFI
2
30
 
3
31
  class Enums
@@ -1,3 +1,31 @@
1
+ #
2
+ # Copyright (C) 2008, 2009 Wayne Meissner
3
+ #
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions are met:
8
+ #
9
+ # * Redistributions of source code must retain the above copyright notice, this
10
+ # list of conditions and the following disclaimer.
11
+ # * Redistributions in binary form must reproduce the above copyright notice
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ # * Neither the name of the Evan Phoenix nor the names of its contributors
15
+ # may be used to endorse or promote products derived from this software
16
+ # without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
22
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+
1
29
  module FFI
2
30
  module IO
3
31
  def self.for_fd(fd, mode = "r")
@@ -1,218 +1,273 @@
1
- module FFI::Library
2
- DEFAULT = FFI::DynamicLibrary.open(nil, FFI::DynamicLibrary::RTLD_LAZY)
3
-
4
- def ffi_lib(*names)
5
- ffi_libs = []
6
- errors = {}
7
- names.each do |name|
8
- [ name, FFI.map_library_name(name) ].each do |libname|
9
- begin
10
- lib = FFI::DynamicLibrary.open(libname, FFI::DynamicLibrary::RTLD_LAZY | FFI::DynamicLibrary::RTLD_GLOBAL)
11
- if lib
12
- ffi_libs << lib
13
- break
14
- end
15
- rescue Exception => ex
16
- errors[name] = ex
17
- end
18
- end
19
- end
20
- if ffi_libs.empty?
21
- msgs = []
22
- errors.each {|name, ex| msgs << "Failed to load library '#{name}': #{ex.message}" }
23
- raise LoadError.new(msgs.join('\n'))
1
+ #
2
+ # Copyright (C) 2008, 2009 Wayne Meissner
3
+ # Copyright (C) 2008 Luc Heinrich <luc@honk-honk.com>
4
+ # Copyright (c) 2007, 2008 Evan Phoenix
5
+ # All rights reserved.
6
+ #
7
+ # Redistribution and use in source and binary forms, with or without
8
+ # modification, are permitted provided that the following conditions are met:
9
+ #
10
+ # * Redistributions of source code must retain the above copyright notice, this
11
+ # list of conditions and the following disclaimer.
12
+ # * Redistributions in binary form must reproduce the above copyright notice
13
+ # this list of conditions and the following disclaimer in the documentation
14
+ # and/or other materials provided with the distribution.
15
+ # * Neither the name of the Evan Phoenix nor the names of its contributors
16
+ # may be used to endorse or promote products derived from this software
17
+ # without specific prior written permission.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
23
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+
30
+ module FFI
31
+ CURRENT_PROCESS = USE_THIS_PROCESS_AS_LIBRARY = Object.new
32
+
33
+ module Library
34
+ CURRENT_PROCESS = FFI::CURRENT_PROCESS
35
+ LIBC = FFI::Platform::LIBC
36
+
37
+ def self.extended(mod)
38
+ raise RuntimeError.new("must only be extended by module") unless mod.kind_of?(Module)
24
39
  end
25
40
 
26
- @ffi_libs = ffi_libs
27
- end
28
- def ffi_convention(convention)
29
- @ffi_convention = convention
30
- end
41
+ def ffi_lib(*names)
31
42
 
32
- def ffi_libraries
33
- unless defined?(@ffi_libs) or self.name.nil?
34
- libs = []
35
- # Try the exact name (e.g. User32) and all lower case (e.g. LibC -> libc)
36
- [ self.name, self.name.downcase ].each do |name|
37
- begin
38
- libs << FFI::DynamicLibrary.open(name, FFI::DynamicLibrary::RTLD_LAZY | FFI::DynamicLibrary::RTLD_GLOBAL)
39
- rescue Exception
43
+ ffi_libs = names.map do |name|
44
+ if name == FFI::CURRENT_PROCESS
45
+ FFI::DynamicLibrary.open(nil, FFI::DynamicLibrary::RTLD_LAZY | FFI::DynamicLibrary::RTLD_GLOBAL)
46
+ else
47
+ libnames = (name.is_a?(::Array) ? name : [ name ]).map { |n| [ n, FFI.map_library_name(n) ].uniq }.flatten.compact
48
+ lib = nil
49
+ errors = {}
50
+
51
+ libnames.each do |libname|
52
+ begin
53
+ lib = FFI::DynamicLibrary.open(libname, FFI::DynamicLibrary::RTLD_LAZY | FFI::DynamicLibrary::RTLD_GLOBAL)
54
+ break if lib
55
+ rescue Exception => ex
56
+ errors[libname] = ex
57
+ end
58
+ end
59
+
60
+ if lib.nil?
61
+ raise LoadError.new(errors.values.join('. '))
62
+ end
63
+
64
+ # return the found lib
65
+ lib
40
66
  end
41
67
  end
42
- @ffi_libs = libs unless libs.empty?
43
- end
44
- defined?(@ffi_libs) ? @ffi_libs : [ DEFAULT ]
45
- end
46
68
 
47
- ##
48
- # Attach C function +name+ to this module.
49
- #
50
- # If you want to provide an alternate name for the module function, supply
51
- # it after the +name+, otherwise the C function name will be used.#
52
- #
53
- # After the +name+, the C function argument types are provided as an Array.
54
- #
55
- # The C function return type is provided last.
56
-
57
- def attach_function(mname, a3, a4, a5=nil)
58
- cname, arg_types, ret_type = a5 ? [ a3, a4, a5 ] : [ mname.to_s, a3, a4 ]
59
-
60
- # Convert :foo to the native type
61
- arg_types.map! { |e| find_type(e) }
62
- has_callback = arg_types.any? {|t| t.kind_of?(FFI::CallbackInfo)}
63
- options = Hash.new
64
- options[:convention] = defined?(@ffi_convention) ? @ffi_convention : :default
65
- options[:type_map] = @ffi_typedefs if defined?(@ffi_typedefs)
66
- options[:enums] = @ffi_enums if defined?(@ffi_enums)
67
-
68
- # Try to locate the function in any of the libraries
69
- invokers = []
70
- ffi_libraries.each do |lib|
71
- begin
72
- invokers << FFI.create_invoker(lib, cname.to_s, arg_types, find_type(ret_type), options)
73
- rescue LoadError => ex
74
- end if invokers.empty?
69
+ @ffi_libs = ffi_libs
75
70
  end
76
- invoker = invokers.compact.shift
77
- raise FFI::NotFoundError.new(cname.to_s, ffi_libraries.map { |lib| lib.name }) unless invoker
78
71
 
79
- # Setup the parameter list for the module function as (a1, a2)
80
- arity = arg_types.length
81
- params = (1..arity).map {|i| "a#{i}" }.join(",")
82
72
 
83
- # Always use rest args for functions with callback parameters
84
- if has_callback || invoker.kind_of?(FFI::VariadicInvoker)
85
- params = "*args, &block"
73
+ def ffi_convention(convention)
74
+ @ffi_convention = convention
86
75
  end
87
- call = arity <= 3 && !has_callback && !invoker.kind_of?(FFI::VariadicInvoker)? "call#{arity}" : "call"
88
76
 
89
- #
90
- # Attach the invoker to this module as 'mname'.
91
- #
92
- if !has_callback && !invoker.kind_of?(FFI::VariadicInvoker)
93
- invoker.attach(self, mname.to_s)
94
- else
95
- self.module_eval <<-code
96
- @@#{mname} = invoker
97
- def self.#{mname}(#{params})
98
- @@#{mname}.#{call}(#{params})
99
- end
100
- def #{mname}(#{params})
101
- @@#{mname}.#{call}(#{params})
102
- end
103
- code
104
- end
105
- invoker
106
- end
107
- def attach_variable(mname, a1, a2 = nil)
108
- cname, type = a2 ? [ a1, a2 ] : [ mname.to_s, a1 ]
109
- address = nil
110
- ffi_libraries.each do |lib|
111
- begin
112
- address = lib.find_variable(cname.to_s)
113
- break unless address.nil?
114
- rescue LoadError
115
- end
77
+
78
+ def ffi_libraries
79
+ raise LoadError.new("no library specified") if !defined?(@ffi_libs) || @ffi_libs.empty?
80
+ @ffi_libs
116
81
  end
117
82
 
118
- raise FFI::NotFoundError.new(cname, ffi_libraries) if address.nil? || address.null?
119
- s = FFI::Struct.new(address, :gvar, find_type(type))
120
-
83
+ ##
84
+ # Attach C function +name+ to this module.
85
+ #
86
+ # If you want to provide an alternate name for the module function, supply
87
+ # it after the +name+, otherwise the C function name will be used.#
121
88
  #
122
- # Attach to this module as mname/mname=
89
+ # After the +name+, the C function argument types are provided as an Array.
123
90
  #
124
- self.module_eval <<-code
125
- @@ffi_gvar_#{mname} = s
126
- def self.#{mname}
127
- @@ffi_gvar_#{mname}[:gvar]
91
+ # The C function return type is provided last.
92
+
93
+ def attach_function(mname, a3, a4, a5=nil)
94
+ cname, arg_types, ret_type = a5 ? [ a3, a4, a5 ] : [ mname.to_s, a3, a4 ]
95
+
96
+ # Convert :foo to the native type
97
+ arg_types.map! { |e| find_type(e) }
98
+ has_callback = arg_types.any? {|t| t.kind_of?(FFI::CallbackInfo)}
99
+ options = Hash.new
100
+ options[:convention] = defined?(@ffi_convention) ? @ffi_convention : :default
101
+ options[:type_map] = @ffi_typedefs if defined?(@ffi_typedefs)
102
+ options[:enums] = @ffi_enums if defined?(@ffi_enums)
103
+
104
+ # Try to locate the function in any of the libraries
105
+ invokers = []
106
+ ffi_libraries.each do |lib|
107
+ begin
108
+ invokers << FFI.create_invoker(lib, cname.to_s, arg_types, find_type(ret_type), options)
109
+ rescue LoadError => ex
110
+ end if invokers.empty?
128
111
  end
129
- def self.#{mname}=(value)
130
- @@ffi_gvar_#{mname}[:gvar] = value
112
+ invoker = invokers.compact.shift
113
+ raise FFI::NotFoundError.new(cname.to_s, ffi_libraries.map { |lib| lib.name }) unless invoker
114
+
115
+ # Setup the parameter list for the module function as (a1, a2)
116
+ arity = arg_types.length
117
+ params = (1..arity).map {|i| "a#{i}" }.join(",")
118
+
119
+ # Always use rest args for functions with callback parameters
120
+ if has_callback || invoker.kind_of?(FFI::VariadicInvoker)
121
+ params = "*args, &block"
131
122
  end
132
- code
133
-
134
- address
135
- end
123
+ call = arity <= 3 && !has_callback && !invoker.kind_of?(FFI::VariadicInvoker)? "call#{arity}" : "call"
136
124
 
137
- def callback(*args)
138
- raise ArgumentError, "wrong number of arguments" if args.length < 2 || args.length > 3
139
- name, params, ret = if args.length == 3
140
- args
141
- else
142
- [ nil, args[0], args[1] ]
125
+ #
126
+ # Attach the invoker to this module as 'mname'.
127
+ #
128
+ if !has_callback && !invoker.kind_of?(FFI::VariadicInvoker)
129
+ invoker.attach(self, mname.to_s)
130
+ else
131
+ self.module_eval <<-code
132
+ @@#{mname} = invoker
133
+ def self.#{mname}(#{params})
134
+ @@#{mname}.#{call}(#{params})
135
+ end
136
+ def #{mname}(#{params})
137
+ @@#{mname}.#{call}(#{params})
138
+ end
139
+ code
140
+ end
141
+ invoker
143
142
  end
144
- cb = FFI::CallbackInfo.new(find_type(ret), params.map { |e| find_type(e) })
143
+ def attach_variable(mname, a1, a2 = nil)
144
+ cname, type = a2 ? [ a1, a2 ] : [ mname.to_s, a1 ]
145
+ address = nil
146
+ ffi_libraries.each do |lib|
147
+ begin
148
+ address = lib.find_variable(cname.to_s)
149
+ break unless address.nil?
150
+ rescue LoadError
151
+ end
152
+ end
153
+
154
+ raise FFI::NotFoundError.new(cname, ffi_libraries) if address.nil? || address.null?
155
+ if type.is_a?(Class) && type < FFI::Struct
156
+ # If it is a global struct, just attach directly to the pointer
157
+ s = type.new(address)
158
+ self.module_eval <<-code, __FILE__, __LINE__
159
+ @@ffi_gvar_#{mname} = s
160
+ def self.#{mname}
161
+ @@ffi_gvar_#{mname}
162
+ end
163
+ code
164
+
165
+ else
166
+ sc = Class.new(FFI::Struct)
167
+ sc.layout :gvar, find_type(type)
168
+ s = sc.new(address)
169
+ #
170
+ # Attach to this module as mname/mname=
171
+ #
172
+ self.module_eval <<-code, __FILE__, __LINE__
173
+ @@ffi_gvar_#{mname} = s
174
+ def self.#{mname}
175
+ @@ffi_gvar_#{mname}[:gvar]
176
+ end
177
+ def self.#{mname}=(value)
178
+ @@ffi_gvar_#{mname}[:gvar] = value
179
+ end
180
+ code
145
181
 
146
- # Add to the symbol -> type map (unless there was no name)
147
- unless name.nil?
148
- @ffi_callbacks = Hash.new unless defined?(@ffi_callbacks)
149
- @ffi_callbacks[name] = cb
182
+ end
183
+
184
+ address
150
185
  end
151
186
 
152
- cb
153
- end
154
-
155
- def typedef(current, add, info=nil)
156
- @ffi_typedefs = Hash.new unless defined?(@ffi_typedefs)
157
- code = if current.kind_of?(FFI::Type)
158
- current
159
- elsif current == :enum
160
- if add.kind_of?(Array)
161
- self.enum(add)
187
+ def callback(*args)
188
+ raise ArgumentError, "wrong number of arguments" if args.length < 2 || args.length > 3
189
+ name, params, ret = if args.length == 3
190
+ args
162
191
  else
163
- self.enum(info, add)
192
+ [ nil, args[0], args[1] ]
164
193
  end
165
- else
166
- @ffi_typedefs[current] || FFI.find_type(current)
194
+
195
+ options = Hash.new
196
+ options[:convention] = defined?(@ffi_convention) ? @ffi_convention : :default
197
+ options[:enums] = @ffi_enums if defined?(@ffi_enums)
198
+ cb = FFI::CallbackInfo.new(find_type(ret), params.map { |e| find_type(e) }, options)
199
+
200
+ # Add to the symbol -> type map (unless there was no name)
201
+ unless name.nil?
202
+ @ffi_callbacks = Hash.new unless defined?(@ffi_callbacks)
203
+ @ffi_callbacks[name] = cb
204
+ end
205
+
206
+ cb
167
207
  end
168
208
 
169
- @ffi_typedefs[add] = code
170
- end
209
+ def typedef(current, add, info=nil)
210
+ @ffi_typedefs = Hash.new unless defined?(@ffi_typedefs)
211
+ code = if current.kind_of?(FFI::Type)
212
+ current
213
+ elsif current == :enum
214
+ if add.kind_of?(Array)
215
+ self.enum(add)
216
+ else
217
+ self.enum(info, add)
218
+ end
219
+ else
220
+ @ffi_typedefs[current] || FFI.find_type(current)
221
+ end
171
222
 
172
- def enum(*args)
173
- #
174
- # enum can be called as:
175
- # enum :zero, :one, :two # unnamed enum
176
- # enum [ :zero, :one, :two ] # equivalent to above
177
- # enum :foo, [ :zero, :one, :two ] create an enum named :foo
178
- #
179
- name, values = if args[0].kind_of?(Symbol) && args[1].kind_of?(Array)
180
- [ args[0], args[1] ]
181
- elsif args[0].kind_of?(Array)
182
- [ nil, args[0] ]
183
- else
184
- [ nil, args ]
223
+ @ffi_typedefs[add] = code
185
224
  end
186
- @ffi_enums = FFI::Enums.new unless defined?(@ffi_enums)
187
- @ffi_enums << (e = FFI::Enum.new(values, name))
188
225
 
189
- # If called as enum :foo, [ :zero, :one, :two ], add a typedef alias
190
- typedef(e, name) if name
191
- e
192
- end
226
+ def enum(*args)
227
+ #
228
+ # enum can be called as:
229
+ # enum :zero, :one, :two # unnamed enum
230
+ # enum [ :zero, :one, :two ] # equivalent to above
231
+ # enum :foo, [ :zero, :one, :two ] create an enum named :foo
232
+ #
233
+ name, values = if args[0].kind_of?(Symbol) && args[1].kind_of?(Array)
234
+ [ args[0], args[1] ]
235
+ elsif args[0].kind_of?(Array)
236
+ [ nil, args[0] ]
237
+ else
238
+ [ nil, args ]
239
+ end
240
+ @ffi_enums = FFI::Enums.new unless defined?(@ffi_enums)
241
+ @ffi_enums << (e = FFI::Enum.new(values, name))
193
242
 
194
- def enum_type(name)
195
- @ffi_enums.find(name) if defined?(@ffi_enums)
196
- end
243
+ # If called as enum :foo, [ :zero, :one, :two ], add a typedef alias
244
+ typedef(e, name) if name
245
+ e
246
+ end
197
247
 
198
- def enum_value(symbol)
199
- @ffi_enums.__map_symbol(symbol)
200
- end
248
+ def enum_type(name)
249
+ @ffi_enums.find(name) if defined?(@ffi_enums)
250
+ end
201
251
 
202
- def find_type(name)
203
- code = if defined?(@ffi_typedefs) && @ffi_typedefs.has_key?(name)
204
- @ffi_typedefs[name]
205
- elsif defined?(@ffi_callbacks) && @ffi_callbacks.has_key?(name)
206
- @ffi_callbacks[name]
207
- elsif name.is_a?(Class) && name < FFI::Struct
208
- FFI::NativeType::POINTER
209
- elsif name.kind_of?(FFI::Type)
210
- name
252
+ def enum_value(symbol)
253
+ @ffi_enums.__map_symbol(symbol)
211
254
  end
212
- if code.nil? || code.kind_of?(Symbol)
213
- FFI.find_type(name)
214
- else
215
- code
255
+
256
+ def find_type(name)
257
+ code = if defined?(@ffi_typedefs) && @ffi_typedefs.has_key?(name)
258
+ @ffi_typedefs[name]
259
+ elsif defined?(@ffi_callbacks) && @ffi_callbacks.has_key?(name)
260
+ @ffi_callbacks[name]
261
+ elsif name.is_a?(Class) && name < FFI::Struct
262
+ FFI::NativeType::POINTER
263
+ elsif name.kind_of?(FFI::Type)
264
+ name
265
+ end
266
+ if code.nil? || code.kind_of?(Symbol)
267
+ FFI.find_type(name)
268
+ else
269
+ code
270
+ end
216
271
  end
217
272
  end
218
273
  end