ffi 1.0.9-x86-mingw32 → 1.0.12.pre-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.

Files changed (218) hide show
  1. data/Rakefile +16 -16
  2. data/ext/ffi_c/AbstractMemory.c +376 -14
  3. data/ext/ffi_c/AbstractMemory.h +8 -0
  4. data/ext/ffi_c/ArrayType.c +28 -0
  5. data/ext/ffi_c/Buffer.c +109 -25
  6. data/ext/ffi_c/Call.c +16 -5
  7. data/ext/ffi_c/ClosurePool.c +21 -8
  8. data/ext/ffi_c/DataConverter.c +29 -0
  9. data/ext/ffi_c/DynamicLibrary.c +71 -2
  10. data/ext/ffi_c/Function.c +122 -11
  11. data/ext/ffi_c/Function.h +6 -0
  12. data/ext/ffi_c/FunctionInfo.c +21 -1
  13. data/ext/ffi_c/LastError.c +24 -0
  14. data/ext/ffi_c/MappedType.c +22 -0
  15. data/ext/ffi_c/MemoryPointer.c +19 -1
  16. data/ext/ffi_c/MemoryPointer.h +6 -0
  17. data/ext/ffi_c/MethodHandle.c +26 -11
  18. data/ext/ffi_c/Platform.c +17 -3
  19. data/ext/ffi_c/Pointer.c +106 -0
  20. data/ext/ffi_c/Pointer.h +6 -0
  21. data/ext/ffi_c/Struct.c +10 -4
  22. data/ext/ffi_c/Struct.h +2 -1
  23. data/ext/ffi_c/StructByReference.c +8 -0
  24. data/ext/ffi_c/StructByValue.c +8 -0
  25. data/ext/ffi_c/StructLayout.c +8 -2
  26. data/ext/ffi_c/Thread.c +131 -1
  27. data/ext/ffi_c/Thread.h +6 -0
  28. data/ext/ffi_c/Type.c +111 -17
  29. data/ext/ffi_c/Types.c +9 -2
  30. data/ext/ffi_c/Types.h +4 -0
  31. data/ext/ffi_c/Variadic.c +13 -4
  32. data/ext/ffi_c/compat.h +8 -0
  33. data/ext/ffi_c/endian.h +10 -1
  34. data/ext/ffi_c/extconf.rb +51 -35
  35. data/ext/ffi_c/ffi.c +5 -0
  36. data/ext/ffi_c/libffi.darwin.mk +15 -15
  37. data/ext/ffi_c/libffi.gnu.mk +3 -3
  38. data/ext/ffi_c/libffi.mk +4 -4
  39. data/ext/ffi_c/libffi.vc.mk +26 -0
  40. data/ext/ffi_c/libffi.vc64.mk +26 -0
  41. data/ext/ffi_c/libffi/ChangeLog +541 -0
  42. data/ext/ffi_c/libffi/ChangeLog.libffi +13 -87
  43. data/ext/ffi_c/libffi/LICENSE +3 -3
  44. data/ext/ffi_c/libffi/Makefile.am +41 -32
  45. data/ext/ffi_c/libffi/Makefile.in +95 -66
  46. data/ext/ffi_c/libffi/Makefile.vc +141 -0
  47. data/ext/ffi_c/libffi/Makefile.vc64 +141 -0
  48. data/ext/ffi_c/libffi/README +40 -4
  49. data/ext/ffi_c/libffi/aclocal.m4 +729 -7854
  50. data/ext/ffi_c/libffi/build-ios.sh +67 -0
  51. data/ext/ffi_c/libffi/compile +11 -10
  52. data/ext/ffi_c/libffi/config.guess +4 -1
  53. data/ext/ffi_c/libffi/config.sub +6 -3
  54. data/ext/ffi_c/libffi/configure +6264 -6354
  55. data/ext/ffi_c/libffi/configure.ac +155 -63
  56. data/ext/ffi_c/libffi/depcomp +81 -35
  57. data/ext/ffi_c/libffi/doc/libffi.info +78 -18
  58. data/ext/ffi_c/libffi/doc/libffi.texi +64 -5
  59. data/ext/ffi_c/libffi/doc/stamp-vti +4 -4
  60. data/ext/ffi_c/libffi/doc/version.texi +4 -4
  61. data/ext/ffi_c/libffi/fficonfig.h.in +18 -0
  62. data/ext/ffi_c/libffi/fficonfig.hw +57 -0
  63. data/ext/ffi_c/libffi/include/Makefile.in +21 -3
  64. data/ext/ffi_c/libffi/include/ffi.h.in +42 -14
  65. data/ext/ffi_c/libffi/include/ffi.h.vc +427 -0
  66. data/ext/ffi_c/libffi/include/ffi.h.vc64 +427 -0
  67. data/ext/ffi_c/libffi/include/ffi_common.h +9 -5
  68. data/ext/ffi_c/libffi/install-sh +364 -167
  69. data/ext/ffi_c/libffi/ltmain.sh +2599 -1369
  70. data/ext/ffi_c/libffi/m4/ax_cc_maxopt.m4 +176 -0
  71. data/ext/ffi_c/libffi/m4/ax_cflags_warn_all.m4 +195 -0
  72. data/ext/ffi_c/libffi/m4/ax_check_compiler_flags.m4 +76 -0
  73. data/ext/ffi_c/libffi/m4/ax_compiler_vendor.m4 +63 -0
  74. data/ext/ffi_c/libffi/m4/ax_configure_args.m4 +70 -0
  75. data/ext/ffi_c/libffi/m4/ax_enable_builddir.m4 +300 -0
  76. data/ext/ffi_c/libffi/m4/ax_gcc_archflag.m4 +215 -0
  77. data/ext/ffi_c/libffi/m4/ax_gcc_x86_cpuid.m4 +79 -0
  78. data/ext/ffi_c/libffi/m4/libtool.m4 +1239 -768
  79. data/ext/ffi_c/libffi/m4/ltoptions.m4 +7 -6
  80. data/ext/ffi_c/libffi/m4/ltversion.m4 +6 -6
  81. data/ext/ffi_c/libffi/m4/lt~obsolete.m4 +9 -3
  82. data/ext/ffi_c/libffi/man/Makefile.in +21 -3
  83. data/ext/ffi_c/libffi/mdate-sh +0 -0
  84. data/ext/ffi_c/libffi/missing +60 -44
  85. data/ext/ffi_c/libffi/msvcc.sh +197 -0
  86. data/ext/ffi_c/libffi/src/alpha/osf.S +39 -18
  87. data/ext/ffi_c/libffi/src/arm/ffi.c +443 -24
  88. data/ext/ffi_c/libffi/src/arm/ffitarget.h +17 -1
  89. data/ext/ffi_c/libffi/src/arm/gentramp.sh +118 -0
  90. data/ext/ffi_c/libffi/src/arm/sysv.S +206 -15
  91. data/ext/ffi_c/libffi/src/arm/trampoline.S +4450 -0
  92. data/ext/ffi_c/libffi/src/avr32/ffi.c +4 -2
  93. data/ext/ffi_c/libffi/src/avr32/ffitarget.h +2 -2
  94. data/ext/ffi_c/libffi/src/closures.c +17 -35
  95. data/ext/ffi_c/libffi/src/cris/ffi.c +1 -1
  96. data/ext/ffi_c/libffi/src/cris/ffitarget.h +2 -2
  97. data/ext/ffi_c/libffi/src/dlmalloc.c +66 -4
  98. data/ext/ffi_c/libffi/src/frv/ffitarget.h +2 -6
  99. data/ext/ffi_c/libffi/src/ia64/ffi.c +7 -5
  100. data/ext/ffi_c/libffi/src/ia64/ffitarget.h +2 -2
  101. data/ext/ffi_c/libffi/src/java_raw_api.c +1 -1
  102. data/ext/ffi_c/libffi/src/m32r/ffitarget.h +2 -2
  103. data/ext/ffi_c/libffi/src/m68k/ffi.c +10 -0
  104. data/ext/ffi_c/libffi/src/m68k/ffitarget.h +2 -2
  105. data/ext/ffi_c/libffi/src/m68k/sysv.S +36 -0
  106. data/ext/ffi_c/libffi/src/mips/ffi.c +12 -5
  107. data/ext/ffi_c/libffi/src/mips/ffitarget.h +18 -11
  108. data/ext/ffi_c/libffi/src/mips/n32.S +4 -4
  109. data/ext/ffi_c/libffi/src/moxie/eabi.S +128 -0
  110. data/ext/ffi_c/libffi/src/moxie/ffi.c +276 -0
  111. data/ext/ffi_c/libffi/src/pa/ffi.c +7 -4
  112. data/ext/ffi_c/libffi/src/pa/ffitarget.h +6 -5
  113. data/ext/ffi_c/libffi/src/powerpc/aix.S +5 -1
  114. data/ext/ffi_c/libffi/src/powerpc/aix_closure.S +2 -0
  115. data/ext/ffi_c/libffi/src/powerpc/asm.h +1 -1
  116. data/ext/ffi_c/libffi/src/powerpc/darwin.S +215 -77
  117. data/ext/ffi_c/libffi/src/powerpc/darwin_closure.S +358 -100
  118. data/ext/ffi_c/libffi/src/powerpc/ffi.c +11 -5
  119. data/ext/ffi_c/libffi/src/powerpc/ffi_darwin.c +603 -172
  120. data/ext/ffi_c/libffi/src/powerpc/ffitarget.h +17 -4
  121. data/ext/ffi_c/libffi/src/prep_cif.c +16 -13
  122. data/ext/ffi_c/libffi/src/s390/ffitarget.h +4 -2
  123. data/ext/ffi_c/libffi/src/sh/ffitarget.h +2 -2
  124. data/ext/ffi_c/libffi/src/sh64/ffitarget.h +2 -2
  125. data/ext/ffi_c/libffi/src/sparc/ffi.c +55 -11
  126. data/ext/ffi_c/libffi/src/sparc/ffitarget.h +5 -3
  127. data/ext/ffi_c/libffi/src/x86/ffi.c +54 -92
  128. data/ext/ffi_c/libffi/src/x86/ffi64.c +17 -8
  129. data/ext/ffi_c/libffi/src/x86/ffitarget.h +15 -14
  130. data/ext/ffi_c/libffi/src/x86/sysv.S +40 -26
  131. data/ext/ffi_c/libffi/src/x86/unix64.S +4 -0
  132. data/ext/ffi_c/libffi/src/x86/win32.S +379 -191
  133. data/ext/ffi_c/libffi/src/x86/win64.S +15 -7
  134. data/ext/ffi_c/libffi/testsuite/Makefile.am +1 -1
  135. data/ext/ffi_c/libffi/testsuite/Makefile.in +22 -4
  136. data/ext/ffi_c/libffi/testsuite/lib/libffi.exp +350 -0
  137. data/ext/ffi_c/libffi/testsuite/libffi.call/call.exp +1 -5
  138. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble_split.c +1 -1
  139. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble_split2.c +1 -1
  140. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint64.c +1 -0
  141. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint64.c +1 -0
  142. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_double_va.c +3 -0
  143. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_longdouble.c +2 -2
  144. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_longdouble_va.c +3 -0
  145. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_pointer.c +1 -1
  146. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_pointer_stack.c +1 -1
  147. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ulonglong.c +1 -0
  148. data/ext/ffi_c/libffi/testsuite/libffi.call/err_bad_abi.c +2 -3
  149. data/ext/ffi_c/libffi/testsuite/libffi.call/err_bad_typedef.c +2 -1
  150. data/ext/ffi_c/libffi/testsuite/libffi.call/ffitest.h +36 -0
  151. data/ext/ffi_c/libffi/testsuite/libffi.call/huge_struct.c +17 -17
  152. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ll1.c +1 -0
  153. data/ext/ffi_c/libffi/testsuite/libffi.call/stret_medium2.c +1 -0
  154. data/ext/ffi_c/libffi/testsuite/libffi.special/ffitestcxx.h +1 -1
  155. data/ext/ffi_c/libffi/testsuite/libffi.special/special.exp +1 -3
  156. data/ext/ffi_c/win32/stdint.h +199 -0
  157. data/gen/Rakefile +18 -2
  158. data/lib/1.8/ffi_c.so +0 -0
  159. data/lib/ffi.rb +13 -9
  160. data/lib/ffi/autopointer.rb +88 -26
  161. data/lib/ffi/enum.rb +42 -0
  162. data/lib/ffi/errno.rb +6 -1
  163. data/lib/ffi/ffi.rb +1 -0
  164. data/lib/ffi/io.rb +13 -2
  165. data/lib/ffi/library.rb +219 -24
  166. data/lib/ffi/memorypointer.rb +1 -33
  167. data/lib/ffi/platform.rb +21 -7
  168. data/lib/ffi/platform/arm-linux/types.conf +102 -0
  169. data/lib/ffi/platform/i386-freebsd/types.conf +152 -0
  170. data/lib/ffi/platform/i386-netbsd/types.conf +126 -0
  171. data/lib/ffi/platform/i486-gnu/types.conf +107 -0
  172. data/lib/ffi/platform/ia64-linux/types.conf +102 -0
  173. data/lib/ffi/platform/mips-linux/types.conf +102 -0
  174. data/lib/ffi/platform/mipsel-linux/types.conf +102 -0
  175. data/lib/ffi/platform/powerpc-linux/types.conf +100 -0
  176. data/lib/ffi/platform/s390-linux/types.conf +102 -0
  177. data/lib/ffi/platform/s390x-linux/types.conf +102 -0
  178. data/lib/ffi/platform/sparc-linux/types.conf +102 -0
  179. data/lib/ffi/platform/x86_64-freebsd/types.conf +126 -0
  180. data/lib/ffi/platform/x86_64-netbsd/types.conf +126 -0
  181. data/lib/ffi/pointer.rb +44 -0
  182. data/lib/ffi/struct.rb +2 -6
  183. data/lib/ffi/struct_layout_builder.rb +2 -1
  184. data/lib/ffi/tools/const_generator.rb +78 -26
  185. data/lib/ffi/tools/types_generator.rb +8 -1
  186. data/lib/ffi/types.rb +21 -1
  187. data/spec/ffi/async_callback_spec.rb +2 -2
  188. data/spec/ffi/bool_spec.rb +6 -6
  189. data/spec/ffi/buffer_spec.rb +23 -23
  190. data/spec/ffi/callback_spec.rb +101 -102
  191. data/spec/ffi/custom_type_spec.rb +20 -24
  192. data/spec/ffi/dup_spec.rb +7 -7
  193. data/spec/ffi/enum_spec.rb +127 -127
  194. data/spec/ffi/errno_spec.rb +2 -2
  195. data/spec/ffi/ffi_spec.rb +3 -3
  196. data/spec/ffi/function_spec.rb +10 -10
  197. data/spec/ffi/library_spec.rb +30 -12
  198. data/spec/ffi/managed_struct_spec.rb +4 -4
  199. data/spec/ffi/number_spec.rb +40 -40
  200. data/spec/ffi/pointer_spec.rb +21 -24
  201. data/spec/ffi/rbx/memory_pointer_spec.rb +17 -15
  202. data/spec/ffi/rbx/struct_spec.rb +2 -2
  203. data/spec/ffi/spec_helper.rb +1 -1
  204. data/spec/ffi/string_spec.rb +9 -9
  205. data/spec/ffi/strptr_spec.rb +3 -3
  206. data/spec/ffi/struct_callback_spec.rb +7 -7
  207. data/spec/ffi/struct_initialize_spec.rb +2 -2
  208. data/spec/ffi/struct_packed_spec.rb +6 -6
  209. data/spec/ffi/struct_spec.rb +94 -84
  210. data/spec/ffi/typedef_spec.rb +15 -4
  211. data/spec/ffi/union_spec.rb +3 -3
  212. data/spec/ffi/variadic_spec.rb +17 -14
  213. data/tasks/extension.rake +0 -1
  214. data/tasks/gem.rake +0 -1
  215. data/tasks/rdoc.rake +1 -1
  216. data/tasks/yard.rake +11 -0
  217. metadata +50 -11
  218. data/lib/1.9/ffi_c.so +0 -0
@@ -1,6 +1,11 @@
1
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
1
2
  require 'fileutils'
2
- require "#{File.join(File.dirname(__FILE__), '..', 'lib', 'ffi', 'tools', 'types_generator.rb')}"
3
- types_conf = File.join(File.dirname(__FILE__), '..', 'lib', 'ffi', 'types.conf')
3
+ require 'ffi'
4
+ require 'ffi/platform'
5
+ require 'ffi/tools/types_generator'
6
+ types_conf = File.expand_path(File.join(FFI::Platform::CONF_DIR, 'types.conf'))
7
+
8
+ logfile = File.join(File.dirname(__FILE__), 'log')
4
9
 
5
10
  file types_conf do |task|
6
11
  options = {}
@@ -8,7 +13,18 @@ file types_conf do |task|
8
13
  File.open(task.name, File::CREAT|File::TRUNC|File::RDWR, 0644) do |f|
9
14
  f.puts FFI::TypesGenerator.generate(options)
10
15
  end
16
+ File.open(logfile, 'w') do |log|
17
+ log.puts(types_conf)
18
+ end
11
19
  end
12
20
 
13
21
  task :default => types_conf do
14
22
  end
23
+
24
+ task :clean do
25
+ File.readlines(logfile).each do |file|
26
+ file.strip!
27
+ rm_f file
28
+ end
29
+ rm_f logfile
30
+ end
Binary file
data/lib/ffi.rb CHANGED
@@ -1,11 +1,15 @@
1
- begin
2
- if RUBY_VERSION =~ /1.8/
3
- require '1.8/ffi_c'
4
- elsif RUBY_VERSION =~ /1.9/
5
- require '1.9/ffi_c'
1
+ if !defined?(RUBY_ENGINE) || RUBY_ENGINE == "ruby"
2
+ begin
3
+ if RUBY_VERSION =~ /1.8/
4
+ require '1.8/ffi_c'
5
+ elsif RUBY_VERSION =~ /1.9/
6
+ require '1.9/ffi_c'
7
+ else
8
+ require 'ffi_c'
9
+ end
10
+ rescue Exception
11
+ require 'ffi_c'
6
12
  end
7
- rescue Exception
8
- require 'ffi_c'
9
- end
10
13
 
11
- require 'ffi/ffi'
14
+ require 'ffi/ffi'
15
+ end
@@ -23,17 +23,31 @@ module FFI
23
23
  class AutoPointer < Pointer
24
24
  extend DataConverter
25
25
 
26
- # call-seq:
27
- # AutoPointer.new(pointer, method) => the passed Method will be invoked at GC time
28
- # AutoPointer.new(pointer, proc) => the passed Proc will be invoked at GC time (SEE WARNING BELOW!)
29
- # AutoPointer.new(pointer) { |p| ... } => the passed block will be invoked at GC time (SEE WARNING BELOW!)
30
- # AutoPointer.new(pointer) => the pointer's release() class method will be invoked at GC time
26
+ # @overload initialize(pointer, method)
27
+ # @param [Pointer] pointer
28
+ # @param [Method] method
29
+ # @return [self]
30
+ # The passed Method will be invoked at GC time.
31
+ # @overload initialize(pointer, proc)
32
+ # @param [Pointer] pointer
33
+ # @return [self]
34
+ # The passed Proc will be invoked at GC time (SEE WARNING BELOW!)
35
+ # @note WARNING: passing a proc _may_ cause your pointer to never be GC'd, unless you're
36
+ # careful to avoid trapping a reference to the pointer in the proc. See the test
37
+ # specs for examples.
38
+ # @overload initialize(pointer) { |p| ... }
39
+ # @param [Pointer] pointer
40
+ # @yieldparam [Pointer] p +pointer+ passed to the block
41
+ # @return [self]
42
+ # The passed block will be invoked at GC time.
43
+ # @note WARNING: passing a block will cause your pointer to never be GC'd. This is bad.
44
+ # @overload initialize(pointer)
45
+ # @param [Pointer] pointer
46
+ # @return [self]
47
+ # The pointer's release() class method will be invoked at GC time.
31
48
  #
32
- # WARNING: passing a proc _may_ cause your pointer to never be GC'd, unless you're careful to avoid trapping a reference to the pointer in the proc. See the test specs for examples.
33
- # WARNING: passing a block will cause your pointer to never be GC'd. This is bad.
34
- #
35
- # Please note that the safest, and therefore preferred, calling
36
- # idiom is to pass a Method as the second parameter. Example usage:
49
+ # @note The safest, and therefore preferred, calling
50
+ # idiom is to pass a Method as the second parameter. Example usage:
37
51
  #
38
52
  # class PointerHelper
39
53
  # def self.release(pointer)
@@ -43,12 +57,12 @@ module FFI
43
57
  #
44
58
  # p = AutoPointer.new(other_pointer, PointerHelper.method(:release))
45
59
  #
46
- # The above code will cause PointerHelper#release to be invoked at GC time.
47
- #
48
- # The last calling idiom (only one parameter) is generally only
49
- # going to be useful if you subclass AutoPointer, and override
50
- # release(), which by default does nothing.
60
+ # The above code will cause PointerHelper#release to be invoked at GC time.
51
61
  #
62
+ # @note
63
+ # The last calling idiom (only one parameter) is generally only
64
+ # going to be useful if you subclass {AutoPointer}, and override
65
+ # #release, which by default does nothing.
52
66
  def initialize(ptr, proc=nil, &block)
53
67
  super(ptr)
54
68
  raise TypeError, "Invalid pointer" if ptr.nil? || !ptr.kind_of?(Pointer) \
@@ -67,52 +81,100 @@ module FFI
67
81
  self
68
82
  end
69
83
 
84
+ # @return [nil]
85
+ # Free the pointer.
70
86
  def free
71
87
  @releaser.free
72
88
  end
73
89
 
90
+ # @param [Boolean] autorelease
91
+ # @return [Boolean] +autorelease+
92
+ # Set +autorelease+ property. See {Pointer Autorelease section at Pointer}.
74
93
  def autorelease=(autorelease)
75
94
  @releaser.autorelease=(autorelease)
76
95
  end
77
96
 
97
+ # @abstract Base class for {AutoPointer}'s releasers.
98
+ #
99
+ # All subclasses of Releaser should define a +#release(ptr)+ method.
100
+ # A releaser is an object in charge of release an {AutoPointer}.
78
101
  class Releaser
102
+ # @param [Pointer] ptr
103
+ # @param [#call] proc
104
+ # @return [nil]
105
+ # A new instance of Releaser.
79
106
  def initialize(ptr, proc)
80
107
  @ptr = ptr
81
108
  @proc = proc
82
109
  @autorelease = true
83
110
  end
84
111
 
112
+ # @return [nil]
113
+ # Free pointer.
85
114
  def free
86
- raise RuntimeError.new("pointer already freed") unless @ptr
87
- @autorelease = false
88
- @ptr = nil
89
- @proc = nil
115
+ if @ptr
116
+ release(@ptr)
117
+ @autorelease = false
118
+ @ptr = nil
119
+ @proc = nil
120
+ end
90
121
  end
91
122
 
123
+ # @param [Boolean] autorelease
124
+ # @return [Boolean] autorelease
125
+ # Set +autorelease+ attribute for pointer managed by Releaser.
92
126
  def autorelease=(autorelease)
93
- raise RuntimeError.new("pointer already freed") unless @ptr
94
- @autorelease = autorelease
127
+ @autorelease = autorelease if @ptr
95
128
  end
96
-
129
+
130
+ # @param args
131
+ # Release pointer if +autorelease+ is set.
132
+ def call(*args)
133
+ release(@ptr) if @autorelease && @ptr
134
+ end
135
+
97
136
  end
98
137
 
138
+ # DefaultReleaser is a {Releaser} used when an {AutoPointer} is defined without Proc
139
+ # or Method. In this case, the pointer to release must be of a class derived from
140
+ # AutoPointer with a +#release+ class method.
99
141
  class DefaultReleaser < Releaser
100
- def call(*args)
101
- @proc.release(@ptr) if @autorelease && @ptr
142
+ # @param [Pointer] ptr
143
+ # @return [nil]
144
+ # Release +ptr+ by using his #release class method.
145
+ def release(ptr)
146
+ @proc.release(ptr)
102
147
  end
103
148
  end
104
149
 
150
+ # CallableReleaser is a {Releaser} used when an {AutoPointer} is defined with a
151
+ # Proc or a Method.
105
152
  class CallableReleaser < Releaser
106
- def call(*args)
107
- @proc.call(@ptr) if @autorelease && @ptr
153
+ # @param [Pointer] ptr
154
+ # @return [nil]
155
+ # Release +ptr+ by using Proc or Method defined at +ptr+ {AutoPointer#initialize initialization}.
156
+ def release(ptr)
157
+ @proc.call(ptr)
108
158
  end
109
159
  end
110
160
 
161
+ # Return native type of AutoPointer.
162
+ #
163
+ # Override {DataConverter#native_type}.
164
+ # @return [Type::POINTER]
165
+ # @raise {RuntimeError} if class does not implement a +#release+ method
111
166
  def self.native_type
112
167
  raise RuntimeError.new("no release method defined for #{self.inspect}") unless self.respond_to?(:release)
113
168
  Type::POINTER
114
169
  end
115
170
 
171
+ # Create a new AutoPointer.
172
+ #
173
+ # Override {DataConverter#from_native}.
174
+ # @overload self.from_native(ptr, ctx)
175
+ # @param [Pointer] ptr
176
+ # @param ctx not used. Please set +nil+.
177
+ # @return [AutoPointer]
116
178
  def self.from_native(val, ctx)
117
179
  self.new(val)
118
180
  end
@@ -21,20 +21,27 @@
21
21
 
22
22
  module FFI
23
23
 
24
+ # An instance of this class permits to manage {Enum}s. In fact, Enums is a collection of {Enum}s.
24
25
  class Enums
25
26
 
27
+ # @return [nil]
26
28
  def initialize
27
29
  @all_enums = Array.new
28
30
  @tagged_enums = Hash.new
29
31
  @symbol_map = Hash.new
30
32
  end
31
33
 
34
+ # @param [Enum] enum
35
+ # Add an {Enum} to the collection.
32
36
  def <<(enum)
33
37
  @all_enums << enum
34
38
  @tagged_enums[enum.tag] = enum unless enum.tag.nil?
35
39
  @symbol_map.merge!(enum.symbol_map)
36
40
  end
37
41
 
42
+ # @param query enum tag or part of an enum name
43
+ # @return [Enum]
44
+ # Find a {Enum} in collection.
38
45
  def find(query)
39
46
  if @tagged_enums.has_key?(query)
40
47
  @tagged_enums[query]
@@ -43,17 +50,33 @@ module FFI
43
50
  end
44
51
  end
45
52
 
53
+ # @param symbol a symbol to find in merge symbol maps of all enums.
54
+ # @return a symbol
46
55
  def __map_symbol(symbol)
47
56
  @symbol_map[symbol]
48
57
  end
49
58
 
50
59
  end
51
60
 
61
+ # Represents a C enum.
62
+ #
63
+ # For a C enum:
64
+ # enum fruits {
65
+ # apple,
66
+ # banana,
67
+ # orange,
68
+ # pineapple
69
+ # };
70
+ # are defined this vocabulary:
71
+ # * a _symbol_ is a word from the enumeration (ie. _apple_, by example);
72
+ # * a _value_ is the value of a symbol in the enumeration (by example, apple has value _0_ and banana _1_).
52
73
  class Enum
53
74
  include DataConverter
54
75
 
55
76
  attr_reader :tag
56
77
 
78
+ # @param [nil, Enumerable] info
79
+ # @param tag enum tag
57
80
  def initialize(info, tag=nil)
58
81
  @tag = tag
59
82
  @kv_map = Hash.new
@@ -75,10 +98,20 @@ module FFI
75
98
  @vk_map = Hash[@kv_map.map{|k,v| [v,k]}]
76
99
  end
77
100
 
101
+ # @return [Array] enum symbol names
78
102
  def symbols
79
103
  @kv_map.keys
80
104
  end
81
105
 
106
+ # Get a symbol or a value from the enum.
107
+ # @overload [](query)
108
+ # Get enum value from symbol.
109
+ # @param [Symbol] query
110
+ # @return [Integer]
111
+ # @overload [](query)
112
+ # Get enum symbol from value.
113
+ # @param [Integer] query
114
+ # @return [Symbol]
82
115
  def [](query)
83
116
  case query
84
117
  when Symbol
@@ -89,6 +122,8 @@ module FFI
89
122
  end
90
123
  alias find []
91
124
 
125
+ # Get the symbol map.
126
+ # @return [Hash]
92
127
  def symbol_map
93
128
  @kv_map
94
129
  end
@@ -96,10 +131,15 @@ module FFI
96
131
  alias to_h symbol_map
97
132
  alias to_hash symbol_map
98
133
 
134
+ # Get native type of Enum
135
+ # @return [Type::INT]
99
136
  def native_type
100
137
  Type::INT
101
138
  end
102
139
 
140
+ # @param [Symbol, Integer, #to_int] val
141
+ # @param ctx unused
142
+ # @return [Integer] value of a enum symbol
103
143
  def to_native(val, ctx)
104
144
  @kv_map[val] || if val.is_a?(Integer)
105
145
  val
@@ -110,6 +150,8 @@ module FFI
110
150
  end
111
151
  end
112
152
 
153
+ # @param val
154
+ # @return symbol name if it exists for +val+.
113
155
  def from_native(val, ctx)
114
156
  @vk_map[val] || val
115
157
  end
@@ -19,10 +19,15 @@
19
19
  #
20
20
 
21
21
  module FFI
22
+ # @return (see FFI::LastError.error)
23
+ # @see FFI::LastError.error
22
24
  def self.errno
23
25
  FFI::LastError.error
24
26
  end
27
+ # @param error (see FFI::LastError.error=)
28
+ # @return (see FFI::LastError.error=)
29
+ # @see FFI::LastError.error=
25
30
  def self.errno=(error)
26
31
  FFI::LastError.error = error
27
32
  end
28
- end
33
+ end
@@ -21,6 +21,7 @@ require 'ffi/platform'
21
21
  require 'ffi/types'
22
22
  require 'ffi/library'
23
23
  require 'ffi/errno'
24
+ require 'ffi/pointer'
24
25
  require 'ffi/memorypointer'
25
26
  require 'ffi/struct'
26
27
  require 'ffi/union'
@@ -19,15 +19,26 @@
19
19
  #
20
20
 
21
21
  module FFI
22
+
23
+ # This module implements a couple of class methods to play with IO.
22
24
  module IO
25
+ # @param [Integer] fd file decriptor
26
+ # @param [String] mode mode string
27
+ # @return [::IO]
28
+ # Synonym for IO::for_fd.
23
29
  def self.for_fd(fd, mode = "r")
24
30
  ::IO.for_fd(fd, mode)
25
31
  end
26
32
 
33
+ # @param [#read] io io to read from
34
+ # @param [AbstractMemory] buf destination for data read from +io+
35
+ # @param [nil, Numeric] len maximul number of bytes to read from +io+. If +nil+,
36
+ # read until end of file.
37
+ # @return [Numeric] length really read, in bytes
27
38
  #
28
- # A version of IO#read that reads into a native buffer
39
+ # A version of IO#read that reads data from an IO and put then into a native buffer.
29
40
  #
30
- # This will be optimized at some future time to eliminate the double copy
41
+ # This will be optimized at some future time to eliminate the double copy.
31
42
  #
32
43
  def self.native_read(io, buf, len)
33
44
  tmp = io.read(len)
@@ -21,6 +21,16 @@
21
21
  module FFI
22
22
  CURRENT_PROCESS = USE_THIS_PROCESS_AS_LIBRARY = Object.new
23
23
 
24
+ # @param [#to_s] lib library name
25
+ # @return [String] library name formatted for current platform
26
+ # Transform a generic library name to a platform library name
27
+ # @example
28
+ # # Linux
29
+ # FFI.map_library_name 'c' # -> "libc.so.6"
30
+ # FFI.map_library_name 'jpeg' # -> "libjpeg.so"
31
+ # # Windows
32
+ # FFI.map_library_name 'c' # -> "msvcrt.dll"
33
+ # FFI.map_library_name 'jpeg' # -> "jpeg.dll"
24
34
  def self.map_library_name(lib)
25
35
  # Mangle the library name to reflect the native library naming conventions
26
36
  lib = lib.to_s unless lib.kind_of?(String)
@@ -28,27 +38,51 @@ module FFI
28
38
 
29
39
  if lib && File.basename(lib) == lib
30
40
  lib = Platform::LIBPREFIX + lib unless lib =~ /^#{Platform::LIBPREFIX}/
31
- r = Platform::IS_LINUX ? "\\.so($|\\.[1234567890]+)" : "\\.#{Platform::LIBSUFFIX}$"
41
+ r = Platform::IS_GNU ? "\\.so($|\\.[1234567890]+)" : "\\.#{Platform::LIBSUFFIX}$"
32
42
  lib += ".#{Platform::LIBSUFFIX}" unless lib =~ /#{r}/
33
43
  end
34
44
 
35
45
  lib
36
46
  end
37
47
 
48
+ # Exception raised when a function is not found in libraries
38
49
  class NotFoundError < LoadError
39
50
  def initialize(function, *libraries)
40
51
  super("Function '#{function}' not found in [#{libraries[0].nil? ? 'current process' : libraries.join(", ")}]")
41
52
  end
42
53
  end
43
54
 
55
+ # This module is the base to use native functions.
56
+ #
57
+ # A basic usage may be:
58
+ # require 'ffi'
59
+ #
60
+ # module Hello
61
+ # extend FFI::Library
62
+ # ffi_lib FFI::Library::LIBC
63
+ # attach_function 'puts', [ :string ], :int
64
+ # end
65
+ #
66
+ # Hello.puts("Hello, World")
67
+ #
68
+ #
44
69
  module Library
45
70
  CURRENT_PROCESS = FFI::CURRENT_PROCESS
46
71
  LIBC = FFI::Platform::LIBC
47
72
 
73
+ # @param mod extended object
74
+ # @return [nil]
75
+ # @raise {RuntimeError} if +mod+ is not a Module
76
+ # Test if extended object is a Module. If not, raise RuntimeError.
48
77
  def self.extended(mod)
49
78
  raise RuntimeError.new("must only be extended by module") unless mod.kind_of?(Module)
50
79
  end
51
80
 
81
+
82
+ # @param [Array] names names of libraries to load
83
+ # @return [Array<DynamicLibrary>]
84
+ # @raise {LoadError} if a library cannot be opened
85
+ # Load native libraries.
52
86
  def ffi_lib(*names)
53
87
  lib_flags = defined?(@ffi_lib_flags) ? @ffi_lib_flags : FFI::DynamicLibrary::RTLD_LAZY | FFI::DynamicLibrary::RTLD_LOCAL
54
88
  ffi_libs = names.map do |name|
@@ -67,12 +101,24 @@ module FFI
67
101
  break if lib
68
102
 
69
103
  rescue Exception => ex
70
- errors[libname] = ex
104
+ ldscript = false
105
+ if ex.message =~ /(([^ \t()])+\.so([^ \t:()])*):([ \t])*invalid ELF header/
106
+ if File.read($1) =~ /GROUP *\( *([^ \)]+) *\)/
107
+ libname = $1
108
+ ldscript = true
109
+ end
110
+ end
111
+
112
+ if ldscript
113
+ retry
114
+ else
115
+ errors[libname] = ex
116
+ end
71
117
  end
72
118
  end
73
119
 
74
120
  if lib.nil?
75
- raise LoadError.new(errors.values.join('. '))
121
+ raise LoadError.new(errors.values.join(".\n"))
76
122
  end
77
123
 
78
124
  # return the found lib
@@ -83,17 +129,32 @@ module FFI
83
129
  @ffi_libs = ffi_libs
84
130
  end
85
131
 
86
-
87
- def ffi_convention(convention)
88
- @ffi_convention = convention
132
+ # Set the calling convention for {#attach_function} and {#callback}
133
+ #
134
+ # @see http://en.wikipedia.org/wiki/Stdcall#stdcall
135
+ # @note +:stdcall+ is typically used for attaching Windows API functions
136
+ #
137
+ # @param [Symbol] convention one of +:default+, +:stdcall+
138
+ # @return [Symbol] the new calling convention
139
+ def ffi_convention(convention = nil)
140
+ @ffi_convention ||= :default
141
+ @ffi_convention = convention if convention
142
+ @ffi_convention
89
143
  end
90
144
 
91
-
145
+ # @see #ffi_lib
146
+ # @return [Array<FFI::DynamicLibrary>] array of currently loaded FFI libraries
147
+ # @raise [LoadError] if no libraries have been loaded (using {#ffi_lib})
148
+ # Get FFI libraries loaded using {#ffi_lib}.
92
149
  def ffi_libraries
93
150
  raise LoadError.new("no library specified") if !defined?(@ffi_libs) || @ffi_libs.empty?
94
151
  @ffi_libs
95
152
  end
96
153
 
154
+ # Flags used in {#ffi_lib}.
155
+ #
156
+ # This map allows you to supply symbols to {#ffi_lib_flags} instead of
157
+ # the actual constants.
97
158
  FlagsMap = {
98
159
  :global => DynamicLibrary::RTLD_GLOBAL,
99
160
  :local => DynamicLibrary::RTLD_LOCAL,
@@ -101,26 +162,64 @@ module FFI
101
162
  :now => DynamicLibrary::RTLD_NOW
102
163
  }
103
164
 
165
+ # Sets library flags for {#ffi_lib}.
166
+ #
167
+ # @example
168
+ # ffi_lib_flags(:lazy, :local) # => 5
169
+ #
170
+ # @param [Symbol, …] flags (see {FlagsMap})
171
+ # @return [Fixnum] the new value
104
172
  def ffi_lib_flags(*flags)
105
173
  @ffi_lib_flags = flags.inject(0) { |result, f| result | FlagsMap[f] }
106
174
  end
107
175
 
108
-
176
+
109
177
  ##
110
- # Attach C function to this module.
178
+ # @overload attach_function(func, args, returns, options = {})
179
+ # @example attach function without an explicit name
180
+ # module Foo
181
+ # extend FFI::Library
182
+ # ffi_lib FFI::Library::LIBC
183
+ # attach_function :malloc, [:size_t], :pointer
184
+ # end
185
+ # # now callable via Foo.malloc
186
+ # @overload attach_function(name, func, args, returns, options = {})
187
+ # @example attach function with an explicit name
188
+ # module Bar
189
+ # extend FFI::Library
190
+ # ffi_lib FFI::Library::LIBC
191
+ # attach_function :c_malloc, :malloc, [:size_t], :pointer
192
+ # end
193
+ # # now callable via Bar.c_malloc
194
+ #
195
+ # Attach C function +func+ to this module.
196
+ #
111
197
  #
112
- def attach_function(mname, a2, a3, a4=nil, a5 = nil)
198
+ # @param [#to_s] name name of ruby method to attach as
199
+ # @param [#to_s] func name of C function to attach
200
+ # @param [Array<Symbol>] args an array of types
201
+ # @param [Symbol] returns type of return value
202
+ # @option options [Boolean] :blocking (@blocking) set to true if the C function is a blocking call
203
+ # @option options [Symbol] :convention (:default) calling convention (see {#ffi_convention})
204
+ # @option options [FFI::Enums] :enums
205
+ # @option options [Hash] :type_map
206
+ #
207
+ # @return [FFI::VariadicInvoker]
208
+ #
209
+ # @raise [FFI::NotFoundError] if +func+ cannot be found in the attached libraries (see {#ffi_lib})
210
+ def attach_function(name, func, args, returns = nil, options = nil)
211
+ mname, a2, a3, a4, a5 = name, func, args, returns, options
113
212
  cname, arg_types, ret_type, opts = (a4 && (a2.is_a?(String) || a2.is_a?(Symbol))) ? [ a2, a3, a4, a5 ] : [ mname.to_s, a2, a3, a4 ]
114
213
 
115
214
  # Convert :foo to the native type
116
215
  arg_types.map! { |e| find_type(e) }
117
216
  options = {
118
- :convention => defined?(@ffi_convention) ? @ffi_convention : :default,
217
+ :convention => ffi_convention,
119
218
  :type_map => defined?(@ffi_typedefs) ? @ffi_typedefs : nil,
120
219
  :blocking => defined?(@blocking) && @blocking,
121
220
  :enums => defined?(@ffi_enums) ? @ffi_enums : nil,
122
221
  }
123
-
222
+
124
223
  @blocking = false
125
224
  options.merge!(opts) if opts && opts.is_a?(Hash)
126
225
 
@@ -129,7 +228,10 @@ module FFI
129
228
  ffi_libraries.each do |lib|
130
229
  if invokers.empty?
131
230
  begin
132
- function = lib.find_function(cname.to_s)
231
+ function = nil
232
+ function_names(cname, arg_types).find do |fname|
233
+ function = lib.find_function(fname)
234
+ end
133
235
  raise LoadError unless function
134
236
 
135
237
  invokers << if arg_types.length > 0 && arg_types[arg_types.length - 1] == FFI::NativeType::VARARGS
@@ -139,7 +241,7 @@ module FFI
139
241
  Function.new(find_type(ret_type), arg_types, function, options)
140
242
  end
141
243
 
142
- rescue LoadError => ex
244
+ rescue LoadError
143
245
  end
144
246
  end
145
247
  end
@@ -150,7 +252,56 @@ module FFI
150
252
  invoker
151
253
  end
152
254
 
255
+ # @param [#to_s] name function name
256
+ # @param [Array] arg_types function's argument types
257
+ # @return [Array<String>]
258
+ # This function returns a list of possible names to lookup.
259
+ # @note Function names on windows may be decorated if they are using stdcall. See
260
+ # * http://en.wikipedia.org/wiki/Name_mangling#C_name_decoration_in_Microsoft_Windows
261
+ # * http://msdn.microsoft.com/en-us/library/zxk0tw93%28v=VS.100%29.aspx
262
+ # * http://en.wikibooks.org/wiki/X86_Disassembly/Calling_Conventions#STDCALL
263
+ # Note that decorated names can be overridden via def files. Also note that the
264
+ # windows api, although using, doesn't have decorated names.
265
+ def function_names(name, arg_types)
266
+ result = [name.to_s]
267
+ if ffi_convention == :stdcall
268
+ # Get the size of each parameter
269
+ size = arg_types.inject(0) do |mem, arg|
270
+ mem + arg.size
271
+ end
272
+
273
+ # Next, the size must be a multiple of 4
274
+ size += (4 - size) % 4
275
+
276
+ result << "_#{name.to_s}@#{size}" # win32
277
+ result << "#{name.to_s}@#{size}" # win64
278
+ end
279
+ result
280
+ end
153
281
 
282
+ # @overload attach_variable(mname, cname, type)
283
+ # @example
284
+ # module Bar
285
+ # extend FFI::Library
286
+ # ffi_lib 'my_lib'
287
+ # attach_variable :c_myvar, :myvar, :long
288
+ # end
289
+ # # now callable via Bar.c_myvar
290
+ # @overload attach_variable(cname, type)
291
+ # @example
292
+ # module Bar
293
+ # extend FFI::Library
294
+ # ffi_lib 'my_lib'
295
+ # attach_variable :myvar, :long
296
+ # end
297
+ # # now callable via Bar.myvar
298
+ # @param [#to_s] mname name of ruby method to attach as
299
+ # @param [#to_s] cname name of C variable to attach
300
+ # @param [DataConverter, Struct, Symbol, Type] type C varaible's type
301
+ # @return [DynamicLibrary::Symbol]
302
+ # @raise {FFI::NotFoundError} if +cname+ cannot be found in libraries
303
+ #
304
+ # Attach C variable +cname+ to this module.
154
305
  def attach_variable(mname, a1, a2 = nil)
155
306
  cname, type = a2 ? [ a1, a2 ] : [ mname.to_s, a1 ]
156
307
  address = nil
@@ -171,7 +322,7 @@ module FFI
171
322
  def self.#{mname}
172
323
  @@ffi_gvar_#{mname}
173
324
  end
174
- code
325
+ code
175
326
 
176
327
  else
177
328
  sc = Class.new(FFI::Struct)
@@ -195,6 +346,13 @@ module FFI
195
346
  address
196
347
  end
197
348
 
349
+
350
+ # @overload callback(name, params, ret)
351
+ # @overload callback(params, ret)
352
+ # @param name callback name to add to type map
353
+ # @param [Array] params array of parameters' types
354
+ # @param [DataConverter, Struct, Symbol, Type] ret callback return type
355
+ # @return [FFI::CallbackInfo]
198
356
  def callback(*args)
199
357
  raise ArgumentError, "wrong number of arguments" if args.length < 2 || args.length > 3
200
358
  name, params, ret = if args.length == 3
@@ -204,7 +362,7 @@ module FFI
204
362
  end
205
363
 
206
364
  options = Hash.new
207
- options[:convention] = defined?(@ffi_convention) ? @ffi_convention : :default
365
+ options[:convention] = ffi_convention
208
366
  options[:enums] = @ffi_enums if defined?(@ffi_enums)
209
367
  cb = FFI::CallbackInfo.new(find_type(ret), params.map { |e| find_type(e) }, options)
210
368
 
@@ -216,6 +374,22 @@ module FFI
216
374
  cb
217
375
  end
218
376
 
377
+ # @param [DataConverter, Symbol, Type] old
378
+ # @param add
379
+ # @param [] info
380
+ # @return [FFI::Enum, FFI::Type]
381
+ # Register or get an already registered type definition.
382
+ #
383
+ # To register a new type definition, +old+ should be a {FFI::Type}. +add+
384
+ # is in this case the type definition.
385
+ #
386
+ # If +old+ is a {DataConverter}, a {Type::Mapped} is returned.
387
+ #
388
+ # If +old+ is +:enum+
389
+ # * and +add+ is an +Array+, a call to {#enum} is made with +add+ as single parameter;
390
+ # * in others cases, +info+ is used to create a named enum.
391
+ #
392
+ # If +old+ is a key for type map, #typedef get +old+ type definition.
219
393
  def typedef(old, add, info=nil)
220
394
  @ffi_typedefs = Hash.new unless defined?(@ffi_typedefs)
221
395
 
@@ -240,13 +414,25 @@ module FFI
240
414
  end
241
415
  end
242
416
 
417
+ # @overload enum(name, values)
418
+ # Create a named enum.
419
+ # @example
420
+ # enum :foo, [:zero, :one, :two] # named enum
421
+ # @param [Symbol] name name for new enum
422
+ # @param [Array] values values for enum
423
+ # @overload enum(*args)
424
+ # Create an unnamed enum.
425
+ # @example
426
+ # enum :zero, :one, :two # unnamed enum
427
+ # @param args values for enum
428
+ # @overload enum(values)
429
+ # Create an unnamed enum.
430
+ # @example
431
+ # enum [:zero, :one, :two] # unnamed enum, equivalent to above example
432
+ # @param [Array] values values for enum
433
+ # @return [FFI::Enum]
434
+ # Create a new {FFI::Enum}.
243
435
  def enum(*args)
244
- #
245
- # enum can be called as:
246
- # enum :zero, :one, :two # unnamed enum
247
- # enum [ :zero, :one, :two ] # equivalent to above
248
- # enum :foo, [ :zero, :one, :two ] create an enum named :foo
249
- #
250
436
  name, values = if args[0].kind_of?(Symbol) && args[1].kind_of?(Array)
251
437
  [ args[0], args[1] ]
252
438
  elsif args[0].kind_of?(Array)
@@ -262,18 +448,27 @@ module FFI
262
448
  e
263
449
  end
264
450
 
451
+ # @param name
452
+ # @return [FFI::Enum]
453
+ # Find an enum by name.
265
454
  def enum_type(name)
266
455
  @ffi_enums.find(name) if defined?(@ffi_enums)
267
456
  end
268
457
 
458
+ # @param symbol
459
+ # @return [FFI::Enum]
460
+ # Find an enum by a symbol it contains.
269
461
  def enum_value(symbol)
270
462
  @ffi_enums.__map_symbol(symbol)
271
463
  end
272
464
 
465
+ # @param [DataConverter, Type, Struct, Symbol] t type to find
466
+ # @return [Type]
467
+ # Find a type definition.
273
468
  def find_type(t)
274
469
  if t.kind_of?(Type)
275
470
  t
276
-
471
+
277
472
  elsif defined?(@ffi_typedefs) && @ffi_typedefs.has_key?(t)
278
473
  @ffi_typedefs[t]
279
474
 
@@ -283,7 +478,7 @@ module FFI
283
478
  elsif t.is_a?(DataConverter)
284
479
  # Add a typedef so next time the converter is used, it hits the cache
285
480
  typedef Type::Mapped.new(t), t
286
-
481
+
287
482
  end || FFI.find_type(t)
288
483
  end
289
484
  end