ffi 0.5.0-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ffi might be problematic. Click here for more details.

Files changed (328) hide show
  1. data/LICENSE +51 -0
  2. data/README.rdoc +69 -0
  3. data/Rakefile +191 -0
  4. data/ext/ffi_c/AbstractMemory.c +489 -0
  5. data/ext/ffi_c/AbstractMemory.h +160 -0
  6. data/ext/ffi_c/ArrayType.c +129 -0
  7. data/ext/ffi_c/ArrayType.h +58 -0
  8. data/ext/ffi_c/AutoPointer.c +61 -0
  9. data/ext/ffi_c/AutoPointer.h +18 -0
  10. data/ext/ffi_c/Buffer.c +187 -0
  11. data/ext/ffi_c/Call.c +853 -0
  12. data/ext/ffi_c/Call.h +86 -0
  13. data/ext/ffi_c/ClosurePool.c +302 -0
  14. data/ext/ffi_c/ClosurePool.h +29 -0
  15. data/ext/ffi_c/DynamicLibrary.c +216 -0
  16. data/ext/ffi_c/DynamicLibrary.h +22 -0
  17. data/ext/ffi_c/Function.c +478 -0
  18. data/ext/ffi_c/Function.h +80 -0
  19. data/ext/ffi_c/FunctionInfo.c +221 -0
  20. data/ext/ffi_c/LastError.c +159 -0
  21. data/ext/ffi_c/LastError.h +18 -0
  22. data/ext/ffi_c/MemoryPointer.c +178 -0
  23. data/ext/ffi_c/MemoryPointer.h +20 -0
  24. data/ext/ffi_c/MethodHandle.c +346 -0
  25. data/ext/ffi_c/MethodHandle.h +53 -0
  26. data/ext/ffi_c/Platform.c +59 -0
  27. data/ext/ffi_c/Platform.h +16 -0
  28. data/ext/ffi_c/Pointer.c +224 -0
  29. data/ext/ffi_c/Pointer.h +49 -0
  30. data/ext/ffi_c/Struct.c +770 -0
  31. data/ext/ffi_c/Struct.h +80 -0
  32. data/ext/ffi_c/StructByValue.c +140 -0
  33. data/ext/ffi_c/StructByValue.h +53 -0
  34. data/ext/ffi_c/StructLayout.c +450 -0
  35. data/ext/ffi_c/Type.c +329 -0
  36. data/ext/ffi_c/Type.h +57 -0
  37. data/ext/ffi_c/Types.c +103 -0
  38. data/ext/ffi_c/Types.h +85 -0
  39. data/ext/ffi_c/Variadic.c +260 -0
  40. data/ext/ffi_c/compat.h +72 -0
  41. data/ext/ffi_c/endian.h +40 -0
  42. data/ext/ffi_c/extconf.rb +30 -0
  43. data/ext/ffi_c/ffi.c +82 -0
  44. data/ext/ffi_c/libffi.bsd.mk +34 -0
  45. data/ext/ffi_c/libffi.darwin.mk +75 -0
  46. data/ext/ffi_c/libffi.gnu.mk +29 -0
  47. data/ext/ffi_c/libffi.mk +13 -0
  48. data/ext/ffi_c/libffi/ChangeLog +3243 -0
  49. data/ext/ffi_c/libffi/ChangeLog.libffi +347 -0
  50. data/ext/ffi_c/libffi/ChangeLog.libgcj +40 -0
  51. data/ext/ffi_c/libffi/ChangeLog.v1 +764 -0
  52. data/ext/ffi_c/libffi/LICENSE +21 -0
  53. data/ext/ffi_c/libffi/Makefile.am +177 -0
  54. data/ext/ffi_c/libffi/Makefile.in +1640 -0
  55. data/ext/ffi_c/libffi/README +328 -0
  56. data/ext/ffi_c/libffi/TODO +1 -0
  57. data/ext/ffi_c/libffi/acinclude.m4 +92 -0
  58. data/ext/ffi_c/libffi/aclocal.m4 +7516 -0
  59. data/ext/ffi_c/libffi/compile +142 -0
  60. data/ext/ffi_c/libffi/config.guess +1516 -0
  61. data/ext/ffi_c/libffi/config.sub +1626 -0
  62. data/ext/ffi_c/libffi/configure +24414 -0
  63. data/ext/ffi_c/libffi/configure.ac +365 -0
  64. data/ext/ffi_c/libffi/configure.host +11 -0
  65. data/ext/ffi_c/libffi/depcomp +584 -0
  66. data/ext/ffi_c/libffi/doc/libffi.info +533 -0
  67. data/ext/ffi_c/libffi/doc/libffi.texi +541 -0
  68. data/ext/ffi_c/libffi/doc/stamp-vti +4 -0
  69. data/ext/ffi_c/libffi/doc/version.texi +4 -0
  70. data/ext/ffi_c/libffi/fficonfig.h.in +160 -0
  71. data/ext/ffi_c/libffi/include/Makefile.am +9 -0
  72. data/ext/ffi_c/libffi/include/Makefile.in +422 -0
  73. data/ext/ffi_c/libffi/include/ffi.h.in +393 -0
  74. data/ext/ffi_c/libffi/include/ffi_common.h +98 -0
  75. data/ext/ffi_c/libffi/install-sh +323 -0
  76. data/ext/ffi_c/libffi/libffi.pc.in +10 -0
  77. data/ext/ffi_c/libffi/libtool-version +29 -0
  78. data/ext/ffi_c/libffi/ltcf-c.sh +861 -0
  79. data/ext/ffi_c/libffi/ltcf-cxx.sh +1069 -0
  80. data/ext/ffi_c/libffi/ltcf-gcj.sh +700 -0
  81. data/ext/ffi_c/libffi/ltconfig +2862 -0
  82. data/ext/ffi_c/libffi/ltmain.sh +6930 -0
  83. data/ext/ffi_c/libffi/man/Makefile.am +8 -0
  84. data/ext/ffi_c/libffi/man/Makefile.in +395 -0
  85. data/ext/ffi_c/libffi/man/ffi.3 +31 -0
  86. data/ext/ffi_c/libffi/man/ffi_call.3 +103 -0
  87. data/ext/ffi_c/libffi/man/ffi_prep_cif.3 +66 -0
  88. data/ext/ffi_c/libffi/mdate-sh +201 -0
  89. data/ext/ffi_c/libffi/missing +353 -0
  90. data/ext/ffi_c/libffi/mkinstalldirs +158 -0
  91. data/ext/ffi_c/libffi/src/alpha/ffi.c +284 -0
  92. data/ext/ffi_c/libffi/src/alpha/ffitarget.h +48 -0
  93. data/ext/ffi_c/libffi/src/alpha/osf.S +366 -0
  94. data/ext/ffi_c/libffi/src/arm/ffi.c +309 -0
  95. data/ext/ffi_c/libffi/src/arm/ffitarget.h +49 -0
  96. data/ext/ffi_c/libffi/src/arm/sysv.S +299 -0
  97. data/ext/ffi_c/libffi/src/closures.c +596 -0
  98. data/ext/ffi_c/libffi/src/cris/ffi.c +383 -0
  99. data/ext/ffi_c/libffi/src/cris/ffitarget.h +51 -0
  100. data/ext/ffi_c/libffi/src/cris/sysv.S +215 -0
  101. data/ext/ffi_c/libffi/src/debug.c +59 -0
  102. data/ext/ffi_c/libffi/src/dlmalloc.c +5099 -0
  103. data/ext/ffi_c/libffi/src/frv/eabi.S +128 -0
  104. data/ext/ffi_c/libffi/src/frv/ffi.c +292 -0
  105. data/ext/ffi_c/libffi/src/frv/ffitarget.h +61 -0
  106. data/ext/ffi_c/libffi/src/ia64/ffi.c +580 -0
  107. data/ext/ffi_c/libffi/src/ia64/ffitarget.h +50 -0
  108. data/ext/ffi_c/libffi/src/ia64/ia64_flags.h +40 -0
  109. data/ext/ffi_c/libffi/src/ia64/unix.S +560 -0
  110. data/ext/ffi_c/libffi/src/java_raw_api.c +359 -0
  111. data/ext/ffi_c/libffi/src/m32r/ffi.c +232 -0
  112. data/ext/ffi_c/libffi/src/m32r/ffitarget.h +48 -0
  113. data/ext/ffi_c/libffi/src/m32r/sysv.S +121 -0
  114. data/ext/ffi_c/libffi/src/m68k/ffi.c +278 -0
  115. data/ext/ffi_c/libffi/src/m68k/ffitarget.h +49 -0
  116. data/ext/ffi_c/libffi/src/m68k/sysv.S +234 -0
  117. data/ext/ffi_c/libffi/src/mips/ffi.c +926 -0
  118. data/ext/ffi_c/libffi/src/mips/ffitarget.h +202 -0
  119. data/ext/ffi_c/libffi/src/mips/n32.S +534 -0
  120. data/ext/ffi_c/libffi/src/mips/o32.S +381 -0
  121. data/ext/ffi_c/libffi/src/pa/ffi.c +709 -0
  122. data/ext/ffi_c/libffi/src/pa/ffitarget.h +77 -0
  123. data/ext/ffi_c/libffi/src/pa/hpux32.S +368 -0
  124. data/ext/ffi_c/libffi/src/pa/linux.S +357 -0
  125. data/ext/ffi_c/libffi/src/powerpc/aix.S +225 -0
  126. data/ext/ffi_c/libffi/src/powerpc/aix_closure.S +247 -0
  127. data/ext/ffi_c/libffi/src/powerpc/asm.h +125 -0
  128. data/ext/ffi_c/libffi/src/powerpc/darwin.S +245 -0
  129. data/ext/ffi_c/libffi/src/powerpc/darwin_closure.S +317 -0
  130. data/ext/ffi_c/libffi/src/powerpc/ffi.c +1429 -0
  131. data/ext/ffi_c/libffi/src/powerpc/ffi_darwin.c +800 -0
  132. data/ext/ffi_c/libffi/src/powerpc/ffitarget.h +118 -0
  133. data/ext/ffi_c/libffi/src/powerpc/linux64.S +187 -0
  134. data/ext/ffi_c/libffi/src/powerpc/linux64_closure.S +236 -0
  135. data/ext/ffi_c/libffi/src/powerpc/ppc_closure.S +327 -0
  136. data/ext/ffi_c/libffi/src/powerpc/sysv.S +230 -0
  137. data/ext/ffi_c/libffi/src/prep_cif.c +174 -0
  138. data/ext/ffi_c/libffi/src/raw_api.c +254 -0
  139. data/ext/ffi_c/libffi/src/s390/ffi.c +780 -0
  140. data/ext/ffi_c/libffi/src/s390/ffitarget.h +60 -0
  141. data/ext/ffi_c/libffi/src/s390/sysv.S +434 -0
  142. data/ext/ffi_c/libffi/src/sh/ffi.c +716 -0
  143. data/ext/ffi_c/libffi/src/sh/ffitarget.h +49 -0
  144. data/ext/ffi_c/libffi/src/sh/sysv.S +850 -0
  145. data/ext/ffi_c/libffi/src/sh64/ffi.c +453 -0
  146. data/ext/ffi_c/libffi/src/sh64/ffitarget.h +53 -0
  147. data/ext/ffi_c/libffi/src/sh64/sysv.S +530 -0
  148. data/ext/ffi_c/libffi/src/sparc/ffi.c +610 -0
  149. data/ext/ffi_c/libffi/src/sparc/ffitarget.h +66 -0
  150. data/ext/ffi_c/libffi/src/sparc/v8.S +272 -0
  151. data/ext/ffi_c/libffi/src/sparc/v9.S +307 -0
  152. data/ext/ffi_c/libffi/src/types.c +77 -0
  153. data/ext/ffi_c/libffi/src/x86/darwin.S +443 -0
  154. data/ext/ffi_c/libffi/src/x86/darwin64.S +416 -0
  155. data/ext/ffi_c/libffi/src/x86/ffi.c +475 -0
  156. data/ext/ffi_c/libffi/src/x86/ffi64.c +572 -0
  157. data/ext/ffi_c/libffi/src/x86/ffitarget.h +90 -0
  158. data/ext/ffi_c/libffi/src/x86/freebsd.S +458 -0
  159. data/ext/ffi_c/libffi/src/x86/sysv.S +437 -0
  160. data/ext/ffi_c/libffi/src/x86/unix64.S +418 -0
  161. data/ext/ffi_c/libffi/src/x86/win32.S +391 -0
  162. data/ext/ffi_c/libffi/testsuite/Makefile.am +71 -0
  163. data/ext/ffi_c/libffi/testsuite/Makefile.in +447 -0
  164. data/ext/ffi_c/libffi/testsuite/config/default.exp +1 -0
  165. data/ext/ffi_c/libffi/testsuite/lib/libffi-dg.exp +289 -0
  166. data/ext/ffi_c/libffi/testsuite/lib/target-libpath.exp +263 -0
  167. data/ext/ffi_c/libffi/testsuite/lib/wrapper.exp +45 -0
  168. data/ext/ffi_c/libffi/testsuite/libffi.call/call.exp +36 -0
  169. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn0.c +97 -0
  170. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn1.c +89 -0
  171. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn2.c +89 -0
  172. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn3.c +90 -0
  173. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn4.c +97 -0
  174. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn5.c +99 -0
  175. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn6.c +98 -0
  176. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_stdcall.c +72 -0
  177. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_12byte.c +102 -0
  178. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_16byte.c +103 -0
  179. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_18byte.c +104 -0
  180. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_19byte.c +110 -0
  181. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_1_1byte.c +97 -0
  182. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_20byte.c +99 -0
  183. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_20byte1.c +101 -0
  184. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_24byte.c +121 -0
  185. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_2byte.c +98 -0
  186. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3_1byte.c +103 -0
  187. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3byte1.c +98 -0
  188. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3byte2.c +98 -0
  189. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_4_1byte.c +106 -0
  190. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_4byte.c +98 -0
  191. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_5_1_byte.c +117 -0
  192. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_5byte.c +106 -0
  193. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_64byte.c +132 -0
  194. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_6_1_byte.c +121 -0
  195. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_6byte.c +107 -0
  196. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_7_1_byte.c +125 -0
  197. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_7byte.c +105 -0
  198. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_8byte.c +96 -0
  199. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_9byte1.c +98 -0
  200. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_9byte2.c +99 -0
  201. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_double.c +101 -0
  202. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_float.c +99 -0
  203. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble.c +100 -0
  204. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_pointer.c +101 -0
  205. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint16.c +99 -0
  206. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint32.c +99 -0
  207. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint64.c +99 -0
  208. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint16.c +99 -0
  209. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint32.c +99 -0
  210. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint64.c +100 -0
  211. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_double.c +51 -0
  212. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_float.c +51 -0
  213. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_schar.c +82 -0
  214. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_sshort.c +82 -0
  215. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_sshortchar.c +94 -0
  216. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_uchar.c +99 -0
  217. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_ushort.c +82 -0
  218. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_ushortchar.c +94 -0
  219. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_schar.c +52 -0
  220. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_sint.c +50 -0
  221. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_sshort.c +50 -0
  222. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uchar.c +50 -0
  223. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uint.c +51 -0
  224. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ulonglong.c +54 -0
  225. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ushort.c +51 -0
  226. data/ext/ffi_c/libffi/testsuite/libffi.call/ffitest.h +86 -0
  227. data/ext/ffi_c/libffi/testsuite/libffi.call/float.c +59 -0
  228. data/ext/ffi_c/libffi/testsuite/libffi.call/float1.c +58 -0
  229. data/ext/ffi_c/libffi/testsuite/libffi.call/float2.c +57 -0
  230. data/ext/ffi_c/libffi/testsuite/libffi.call/float3.c +72 -0
  231. data/ext/ffi_c/libffi/testsuite/libffi.call/float4.c +62 -0
  232. data/ext/ffi_c/libffi/testsuite/libffi.call/many.c +69 -0
  233. data/ext/ffi_c/libffi/testsuite/libffi.call/many_win32.c +63 -0
  234. data/ext/ffi_c/libffi/testsuite/libffi.call/negint.c +53 -0
  235. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct.c +160 -0
  236. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct1.c +169 -0
  237. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct10.c +141 -0
  238. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct2.c +118 -0
  239. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct3.c +119 -0
  240. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct4.c +119 -0
  241. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct5.c +120 -0
  242. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct6.c +139 -0
  243. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct7.c +119 -0
  244. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct8.c +139 -0
  245. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct9.c +139 -0
  246. data/ext/ffi_c/libffi/testsuite/libffi.call/problem1.c +98 -0
  247. data/ext/ffi_c/libffi/testsuite/libffi.call/promotion.c +59 -0
  248. data/ext/ffi_c/libffi/testsuite/libffi.call/pyobjc-tc.c +114 -0
  249. data/ext/ffi_c/libffi/testsuite/libffi.call/return_dbl.c +35 -0
  250. data/ext/ffi_c/libffi/testsuite/libffi.call/return_dbl1.c +43 -0
  251. data/ext/ffi_c/libffi/testsuite/libffi.call/return_dbl2.c +42 -0
  252. data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl.c +35 -0
  253. data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl1.c +36 -0
  254. data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl2.c +49 -0
  255. data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl3.c +42 -0
  256. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ldl.c +34 -0
  257. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ll.c +41 -0
  258. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ll1.c +42 -0
  259. data/ext/ffi_c/libffi/testsuite/libffi.call/return_sc.c +36 -0
  260. data/ext/ffi_c/libffi/testsuite/libffi.call/return_sl.c +38 -0
  261. data/ext/ffi_c/libffi/testsuite/libffi.call/return_uc.c +38 -0
  262. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ul.c +38 -0
  263. data/ext/ffi_c/libffi/testsuite/libffi.call/strlen.c +44 -0
  264. data/ext/ffi_c/libffi/testsuite/libffi.call/strlen_win32.c +44 -0
  265. data/ext/ffi_c/libffi/testsuite/libffi.call/struct1.c +65 -0
  266. data/ext/ffi_c/libffi/testsuite/libffi.call/struct2.c +67 -0
  267. data/ext/ffi_c/libffi/testsuite/libffi.call/struct3.c +59 -0
  268. data/ext/ffi_c/libffi/testsuite/libffi.call/struct4.c +63 -0
  269. data/ext/ffi_c/libffi/testsuite/libffi.call/struct5.c +65 -0
  270. data/ext/ffi_c/libffi/testsuite/libffi.call/struct6.c +64 -0
  271. data/ext/ffi_c/libffi/testsuite/libffi.call/struct7.c +74 -0
  272. data/ext/ffi_c/libffi/testsuite/libffi.call/struct8.c +80 -0
  273. data/ext/ffi_c/libffi/testsuite/libffi.call/struct9.c +67 -0
  274. data/ext/ffi_c/libffi/testsuite/libffi.special/ffitestcxx.h +86 -0
  275. data/ext/ffi_c/libffi/testsuite/libffi.special/special.exp +38 -0
  276. data/ext/ffi_c/libffi/testsuite/libffi.special/unwindtest.cc +123 -0
  277. data/ext/ffi_c/libffi/testsuite/libffi.special/unwindtest_ffi_call.cc +53 -0
  278. data/ext/ffi_c/libffi/texinfo.tex +7482 -0
  279. data/ext/ffi_c/rbffi.h +26 -0
  280. data/gen/Rakefile +12 -0
  281. data/lib/1.8/ffi_c.so +0 -0
  282. data/lib/1.9/ffi_c.so +0 -0
  283. data/lib/ffi.rb +11 -0
  284. data/lib/ffi/autopointer.rb +61 -0
  285. data/lib/ffi/buffer.rb +0 -0
  286. data/lib/ffi/callback.rb +10 -0
  287. data/lib/ffi/enum.rb +78 -0
  288. data/lib/ffi/errno.rb +8 -0
  289. data/lib/ffi/ffi.rb +99 -0
  290. data/lib/ffi/io.rb +21 -0
  291. data/lib/ffi/library.rb +218 -0
  292. data/lib/ffi/managedstruct.rb +55 -0
  293. data/lib/ffi/memorypointer.rb +73 -0
  294. data/lib/ffi/platform.rb +88 -0
  295. data/lib/ffi/pointer.rb +119 -0
  296. data/lib/ffi/struct.rb +183 -0
  297. data/lib/ffi/tools/const_generator.rb +177 -0
  298. data/lib/ffi/tools/generator.rb +58 -0
  299. data/lib/ffi/tools/generator_task.rb +35 -0
  300. data/lib/ffi/tools/struct_generator.rb +194 -0
  301. data/lib/ffi/tools/types_generator.rb +123 -0
  302. data/lib/ffi/types.rb +153 -0
  303. data/lib/ffi/union.rb +12 -0
  304. data/lib/ffi/variadic.rb +25 -0
  305. data/spec/ffi/bool_spec.rb +24 -0
  306. data/spec/ffi/buffer_spec.rb +202 -0
  307. data/spec/ffi/callback_spec.rb +591 -0
  308. data/spec/ffi/enum_spec.rb +164 -0
  309. data/spec/ffi/errno_spec.rb +13 -0
  310. data/spec/ffi/function_spec.rb +73 -0
  311. data/spec/ffi/library_spec.rb +148 -0
  312. data/spec/ffi/managed_struct_spec.rb +56 -0
  313. data/spec/ffi/number_spec.rb +231 -0
  314. data/spec/ffi/pointer_spec.rb +195 -0
  315. data/spec/ffi/rbx/attach_function_spec.rb +27 -0
  316. data/spec/ffi/rbx/memory_pointer_spec.rb +102 -0
  317. data/spec/ffi/rbx/spec_helper.rb +1 -0
  318. data/spec/ffi/rbx/struct_spec.rb +13 -0
  319. data/spec/ffi/spec_helper.rb +17 -0
  320. data/spec/ffi/string_spec.rb +103 -0
  321. data/spec/ffi/struct_callback_spec.rb +64 -0
  322. data/spec/ffi/struct_initialize_spec.rb +30 -0
  323. data/spec/ffi/struct_spec.rb +529 -0
  324. data/spec/ffi/typedef_spec.rb +48 -0
  325. data/spec/ffi/union_spec.rb +60 -0
  326. data/spec/ffi/variadic_spec.rb +84 -0
  327. data/spec/spec.opts +4 -0
  328. metadata +396 -0
@@ -0,0 +1,102 @@
1
+ require "rubygems"
2
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
3
+
4
+ module CTest
5
+ extend FFI::Library
6
+
7
+ attach_function :strcat, [:pointer, :pointer], :pointer
8
+ end
9
+
10
+ describe "MemoryPointer" do
11
+ it "makes a pointer from a string" do
12
+ m = FFI::MemoryPointer.from_string("FFI is Awesome")
13
+ m.type_size.should == 15
14
+ end
15
+
16
+ it "reads back a string" do
17
+ m = FFI::MemoryPointer.from_string("FFI is Awesome")
18
+ m.read_string.should == "FFI is Awesome"
19
+ end
20
+
21
+ it "makes a pointer for a certain number of bytes" do
22
+ m = FFI::MemoryPointer.new(8)
23
+ m.write_array_of_int([1,2])
24
+ m.read_array_of_int(2).should == [1,2]
25
+ end
26
+
27
+ it "allows access to an element of the pointer (as an array)" do
28
+ m = FFI::MemoryPointer.new(:int, 2)
29
+ m.write_array_of_int([1,2])
30
+ m[0].read_int.should == 1
31
+ m[1].read_int.should == 2
32
+ end
33
+
34
+ it "allows writing as an int" do
35
+ m = FFI::MemoryPointer.new(:int)
36
+ m.write_int(1)
37
+ m.read_int.should == 1
38
+ end
39
+
40
+ it "allows writing as a long" do
41
+ m = FFI::MemoryPointer.new(:long)
42
+ m.write_long(10)
43
+ m.read_long.should == 10
44
+ end
45
+
46
+ it "raises an error if you try putting a long into a pointer of size 1" do
47
+ m = FFI::MemoryPointer.new(1)
48
+ lambda { m.write_long(10) }.should raise_error
49
+ end
50
+
51
+ it "raises an error if you try putting an int into a pointer of size 1" do
52
+ m = FFI::MemoryPointer.new(1)
53
+ lambda { m.write_int(10) }.should raise_error
54
+ end
55
+ # it "does not raise IndexError for opaque pointers" do
56
+ # m = FFI::MemoryPointer.new(8)
57
+ # p2 = FFI::MemoryPointer.new(1024)
58
+ # m.write_long(p2.address)
59
+ # p = m.read_pointer
60
+ # lambda { p.write_int(10) }.should_not raise_error
61
+ # end
62
+
63
+ it "makes a pointer for a certain type" do
64
+ m = FFI::MemoryPointer.new(:int)
65
+ m.write_int(10)
66
+ m.read_int.should == 10
67
+ end
68
+
69
+ it "makes a memory pointer for a number of a certain type" do
70
+ m = FFI::MemoryPointer.new(:int, 2)
71
+ m.write_array_of_int([1,2])
72
+ m.read_array_of_int(2).should == [1,2]
73
+ end
74
+
75
+ it "makes a pointer for an object responding to #size" do
76
+ m = FFI::MemoryPointer.new(Struct.new(:size).new(8))
77
+ m.write_array_of_int([1,2])
78
+ m.read_array_of_int(2).should == [1,2]
79
+ end
80
+
81
+ it "makes a pointer for a number of an object responding to #size" do
82
+ m = FFI::MemoryPointer.new(Struct.new(:size).new(4), 2)
83
+ m.write_array_of_int([1,2])
84
+ m.read_array_of_int(2).should == [1,2]
85
+ end
86
+ it "MemoryPointer#address returns correct value" do
87
+ m = FFI::MemoryPointer.new(:long_long)
88
+ magic = 0x12345678
89
+ m.write_long(magic)
90
+ m.read_pointer.address.should == magic
91
+ end
92
+ it "MemoryPointer#null? returns true for zero value" do
93
+ m = FFI::MemoryPointer.new(:long_long)
94
+ m.write_long(0)
95
+ m.read_pointer.null?.should == true
96
+ end
97
+ it "MemoryPointer#null? returns false for non-zero value" do
98
+ m = FFI::MemoryPointer.new(:long_long)
99
+ m.write_long(0x12345678)
100
+ m.read_pointer.null?.should == false
101
+ end
102
+ end
@@ -0,0 +1 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper"))
@@ -0,0 +1,13 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
2
+
3
+ class Timeval < FFI::Struct
4
+ layout :tv_sec, :ulong, 0, :tv_usec, :ulong, 4
5
+ end
6
+
7
+ describe FFI::Struct do
8
+ it "allows setting fields" do
9
+ t = Timeval.new
10
+ t[:tv_sec] = 12
11
+ t[:tv_sec].should == 12
12
+ end
13
+ end
@@ -0,0 +1,17 @@
1
+ require 'rubygems'
2
+ require 'rbconfig'
3
+ require 'spec'
4
+
5
+ if ENV["MRI_FFI"]
6
+ $:.unshift File.join(File.dirname(__FILE__), "..", "..", "lib"),
7
+ File.join(File.dirname(__FILE__), "..", "..", "build", "#{Config::CONFIG['host_cpu''arch']}", "ffi_c", RUBY_VERSION)
8
+ end
9
+ require "ffi"
10
+
11
+ module TestLibrary
12
+ PATH = "build/libtest.#{FFI::Platform::LIBSUFFIX}"
13
+ end
14
+ module LibTest
15
+ extend FFI::Library
16
+ ffi_lib TestLibrary::PATH
17
+ end
@@ -0,0 +1,103 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
2
+ describe "String tests" do
3
+ include FFI
4
+ module StrLibTest
5
+ extend FFI::Library
6
+ ffi_lib TestLibrary::PATH
7
+ attach_function :ptr_ret_pointer, [ :pointer, :int], :string
8
+ attach_function :string_equals, [ :string, :string ], :int
9
+ attach_function :string_dummy, [ :string ], :void
10
+ attach_function :string_null, [ ], :string
11
+ end
12
+ it "MemoryPointer#get_string returns a tainted string" do
13
+ mp = MemoryPointer.new 1024
14
+ mp.put_string(0, "test\0")
15
+ str = mp.get_string(0)
16
+ str.tainted?.should == true
17
+ end
18
+ it "String returned by a method is tainted" do
19
+ mp = MemoryPointer.new :pointer
20
+ sp = MemoryPointer.new 1024
21
+ sp.put_string(0, "test")
22
+ mp.put_pointer(0, sp)
23
+ str = StrLibTest.ptr_ret_pointer(mp, 0)
24
+ str.should == "test"
25
+ str.tainted?.should == true
26
+ end
27
+ it "Poison null byte raises error" do
28
+ s = "123\0abc"
29
+ lambda { StrLibTest.string_equals(s, s) }.should raise_error
30
+ end
31
+ it "Tainted String parameter should throw a SecurityError" do
32
+ $SAFE = 1
33
+ str = "test"
34
+ str.taint
35
+ begin
36
+ LibTest.string_equals(str, str).should == false
37
+ rescue SecurityError => e
38
+ end
39
+ end if false
40
+ it "casts nil as NULL pointer" do
41
+ StrLibTest.string_dummy(nil)
42
+ end
43
+ it "return nil for NULL char*" do
44
+ StrLibTest.string_null.should == nil
45
+ end
46
+ it "reads an array of strings until encountering a NULL pointer" do
47
+ strings = ["foo", "bar", "baz", "testing", "ffi"]
48
+ ptrary = MemoryPointer.new(:pointer, 6)
49
+ ary = strings.inject([]) do |a, str|
50
+ f = MemoryPointer.new(1024)
51
+ f.put_string(0, str)
52
+ a << f
53
+ end
54
+ ary.insert(3, nil)
55
+ ptrary.write_array_of_pointer(ary)
56
+ ptrary.get_array_of_string(0).should == ["foo", "bar", "baz"]
57
+ end
58
+ it "reads an array of strings of the size specified, substituting nil when a pointer is NULL" do
59
+ strings = ["foo", "bar", "baz", "testing", "ffi"]
60
+ ptrary = MemoryPointer.new(:pointer, 6)
61
+ ary = strings.inject([]) do |a, str|
62
+ f = MemoryPointer.new(1024)
63
+ f.put_string(0, str)
64
+ a << f
65
+ end
66
+ ary.insert(2, nil)
67
+ ptrary.write_array_of_pointer(ary)
68
+ ptrary.get_array_of_string(0, 4).should == ["foo", "bar", nil, "baz"]
69
+ end
70
+ it "reads an array of strings, taking a memory offset parameter" do
71
+ strings = ["foo", "bar", "baz", "testing", "ffi"]
72
+ ptrary = MemoryPointer.new(:pointer, 5)
73
+ ary = strings.inject([]) do |a, str|
74
+ f = MemoryPointer.new(1024)
75
+ f.put_string(0, str)
76
+ a << f
77
+ end
78
+ ptrary.write_array_of_pointer(ary)
79
+ ptrary.get_array_of_string(2 * FFI.type_size(:pointer), 3).should == ["baz", "testing", "ffi"]
80
+ end
81
+ it "raises an IndexError when trying to read an array of strings out of bounds" do
82
+ strings = ["foo", "bar", "baz", "testing", "ffi"]
83
+ ptrary = MemoryPointer.new(:pointer, 5)
84
+ ary = strings.inject([]) do |a, str|
85
+ f = MemoryPointer.new(1024)
86
+ f.put_string(0, str)
87
+ a << f
88
+ end
89
+ ptrary.write_array_of_pointer(ary)
90
+ lambda { ptrary.get_array_of_string(0, 6) }.should raise_error
91
+ end
92
+ it "raises an IndexError when trying to read an array of strings using a negative offset" do
93
+ strings = ["foo", "bar", "baz", "testing", "ffi"]
94
+ ptrary = MemoryPointer.new(:pointer, 5)
95
+ ary = strings.inject([]) do |a, str|
96
+ f = MemoryPointer.new(1024)
97
+ f.put_string(0, str)
98
+ a << f
99
+ end
100
+ ptrary.write_array_of_pointer(ary)
101
+ lambda { ptrary.get_array_of_string(-1) }.should raise_error
102
+ end
103
+ end
@@ -0,0 +1,64 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
2
+
3
+ describe FFI::Struct, ' with inline callback functions' do
4
+ it 'should be able to define inline callback field' do
5
+ module CallbackMember
6
+ extend FFI::Library
7
+ ffi_lib TestLibrary::PATH
8
+ DUMMY_CB = callback :dummy_cb, [ :int ], :int
9
+ class TestStruct < FFI::Struct
10
+ layout \
11
+ :add, callback([ :int, :int ], :int),
12
+ :sub, callback([ :int, :int ], :int),
13
+ :cb_with_cb_parameter, callback([ DUMMY_CB, :int ], :int)
14
+ end
15
+ attach_function :struct_call_add_cb, [TestStruct, :int, :int], :int
16
+ attach_function :struct_call_sub_cb, [TestStruct, :int, :int], :int
17
+ end
18
+ end
19
+ it 'should take methods as callbacks' do
20
+ module CallbackMember
21
+ extend FFI::Library
22
+ ffi_lib TestLibrary::PATH
23
+ class TestStruct < FFI::Struct
24
+ layout \
25
+ :add, callback([ :int, :int ], :int),
26
+ :sub, callback([ :int, :int ], :int)
27
+ end
28
+ attach_function :struct_call_add_cb, [TestStruct, :int, :int], :int
29
+ attach_function :struct_call_sub_cb, [TestStruct, :int, :int], :int
30
+ end
31
+ module StructCallbacks
32
+ def self.add a, b
33
+ a+b
34
+ end
35
+ end
36
+
37
+ ts = CallbackMember::TestStruct.new
38
+ ts[:add] = StructCallbacks.method(:add)
39
+
40
+ CallbackMember.struct_call_add_cb(ts, 1, 2).should == 3
41
+ end
42
+
43
+ it 'should return callable object from []' do
44
+ module CallbackMember
45
+ extend FFI::Library
46
+ ffi_lib TestLibrary::PATH
47
+ class TestStruct < FFI::Struct
48
+ layout \
49
+ :add, callback([ :int, :int ], :int),
50
+ :sub, callback([ :int, :int ], :int)
51
+ end
52
+ attach_function :struct_call_add_cb, [TestStruct, :int, :int], :int
53
+ attach_function :struct_call_sub_cb, [TestStruct, :int, :int], :int
54
+ end
55
+
56
+ s = CallbackMember::TestStruct.new
57
+ add = Proc.new { |a,b| a+b}
58
+ s[:add] = add
59
+ fn = s[:add]
60
+ fn.respond_to?(:call).should be_true
61
+ fn.call(1, 2).should == 3
62
+ end
63
+ end
64
+
@@ -0,0 +1,30 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
2
+
3
+ describe FFI::Struct, ' with an initialize function' do
4
+ it "should call the initialize function" do
5
+ class StructWithInitialize < FFI::Struct
6
+ layout :string, :string
7
+ attr_accessor :magic
8
+ def initialize
9
+ super
10
+ self.magic = 42
11
+ end
12
+ end
13
+ StructWithInitialize.new.magic.should == 42
14
+ end
15
+ end
16
+
17
+ describe FFI::ManagedStruct, ' with an initialize function' do
18
+ it "should call the initialize function" do
19
+ class ManagedStructWithInitialize < FFI::ManagedStruct
20
+ layout :string, :string
21
+ attr_accessor :magic
22
+ def initialize
23
+ super MemoryPointer.new(:pointer).put_int(0, 0x1234).get_pointer(0)
24
+ self.magic = 42
25
+ end
26
+ def self.release;end
27
+ end
28
+ ManagedStructWithInitialize.new.magic.should == 42
29
+ end
30
+ end
@@ -0,0 +1,529 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
2
+ describe "Struct tests" do
3
+ StructTypes = {
4
+ 's8' => :char,
5
+ 's16' => :short,
6
+ 's32' => :int,
7
+ 's64' => :long_long,
8
+ 'long' => :long,
9
+ 'f32' => :float,
10
+ 'f64' => :double
11
+ }
12
+ module LibTest
13
+ extend FFI::Library
14
+ ffi_lib TestLibrary::PATH
15
+ attach_function :ptr_ret_pointer, [ :pointer, :int], :string
16
+ attach_function :ptr_ret_int32_t, [ :pointer, :int ], :int
17
+ attach_function :ptr_from_address, [ :ulong ], :pointer
18
+ attach_function :string_equals, [ :string, :string ], :int
19
+ [ 's8', 's16', 's32', 's64', 'f32', 'f64', 'long' ].each do |t|
20
+ attach_function "struct_align_#{t}", [ :pointer ], StructTypes[t]
21
+ end
22
+ end
23
+ class PointerMember < FFI::Struct
24
+ layout :pointer, :pointer
25
+ end
26
+ class StringMember < FFI::Struct
27
+ layout :string, :string
28
+ end
29
+ it "Struct#[:pointer]" do
30
+ magic = 0x12345678
31
+ mp = FFI::MemoryPointer.new :long
32
+ mp.put_long(0, magic)
33
+ smp = FFI::MemoryPointer.new :pointer
34
+ smp.put_pointer(0, mp)
35
+ s = PointerMember.new smp
36
+ s[:pointer].should == mp
37
+ end
38
+ it "Struct#[:pointer].nil? for NULL value" do
39
+ magic = 0x12345678
40
+ mp = FFI::MemoryPointer.new :long
41
+ mp.put_long(0, magic)
42
+ smp = FFI::MemoryPointer.new :pointer
43
+ smp.put_pointer(0, nil)
44
+ s = PointerMember.new smp
45
+ s[:pointer].null?.should == true
46
+ end
47
+ it "Struct#[:pointer]=" do
48
+ magic = 0x12345678
49
+ mp = FFI::MemoryPointer.new :long
50
+ mp.put_long(0, magic)
51
+ smp = FFI::MemoryPointer.new :pointer
52
+ s = PointerMember.new smp
53
+ s[:pointer] = mp
54
+ smp.get_pointer(0).should == mp
55
+ end
56
+ it "Struct#[:pointer]=struct" do
57
+ magic = 0x12345678
58
+ smp = FFI::MemoryPointer.new :pointer
59
+ s = PointerMember.new smp
60
+ lambda { s[:pointer] = s }.should_not raise_error
61
+ end
62
+ it "Struct#[:pointer]=nil" do
63
+ smp = FFI::MemoryPointer.new :pointer
64
+ s = PointerMember.new smp
65
+ s[:pointer] = nil
66
+ smp.get_pointer(0).null?.should == true
67
+ end
68
+ it "Struct#[:string]" do
69
+ magic = "test"
70
+ mp = FFI::MemoryPointer.new 1024
71
+ mp.put_string(0, magic)
72
+ smp = FFI::MemoryPointer.new :pointer
73
+ smp.put_pointer(0, mp)
74
+ s = StringMember.new smp
75
+ s[:string].should == magic
76
+ end
77
+ it "Struct#[:string].nil? for NULL value" do
78
+ smp = FFI::MemoryPointer.new :pointer
79
+ smp.put_pointer(0, nil)
80
+ s = StringMember.new smp
81
+ s[:string].nil?.should == true
82
+ end
83
+ it "Struct#layout works with :name, :type pairs" do
84
+ class PairLayout < FFI::Struct
85
+ layout :a, :int, :b, :long_long
86
+ end
87
+ ll_off = (FFI::TYPE_UINT64.alignment == 4 ? 4 : 8)
88
+ PairLayout.size.should == (ll_off + 8)
89
+ mp = FFI::MemoryPointer.new(PairLayout.size)
90
+ s = PairLayout.new mp
91
+ s[:a] = 0x12345678
92
+ mp.get_int(0).should == 0x12345678
93
+ s[:b] = 0xfee1deadbeef
94
+ mp.get_int64(ll_off).should == 0xfee1deadbeef
95
+ end
96
+ it "Struct#layout works with :name, :type, offset tuples" do
97
+ class PairLayout < FFI::Struct
98
+ layout :a, :int, 0, :b, :long_long, 4
99
+ end
100
+ PairLayout.size.should == (FFI::TYPE_UINT64.alignment == 4 ? 12 : 16)
101
+ mp = FFI::MemoryPointer.new(PairLayout.size)
102
+ s = PairLayout.new mp
103
+ s[:a] = 0x12345678
104
+ mp.get_int(0).should == 0x12345678
105
+ s[:b] = 0xfee1deadbeef
106
+ mp.get_int64(4).should == 0xfee1deadbeef
107
+ end
108
+ it "Struct#layout works with mixed :name,:type and :name,:type,offset" do
109
+ class MixedLayout < FFI::Struct
110
+ layout :a, :int, :b, :long_long, 4
111
+ end
112
+ MixedLayout.size.should == (FFI::TYPE_UINT64.alignment == 4 ? 12 : 16)
113
+ mp = FFI::MemoryPointer.new(MixedLayout.size)
114
+ s = MixedLayout.new mp
115
+ s[:a] = 0x12345678
116
+ mp.get_int(0).should == 0x12345678
117
+ s[:b] = 0xfee1deadbeef
118
+ mp.get_int64(4).should == 0xfee1deadbeef
119
+ end
120
+ rb_maj, rb_min = RUBY_VERSION.split('.')
121
+ if rb_maj.to_i >= 1 && rb_min.to_i >= 9 || RUBY_PLATFORM =~ /java/
122
+ it "Struct#layout withs with a hash of :name => type" do
123
+ class HashLayout < FFI::Struct
124
+ layout :a => :int, :b => :long_long
125
+ end
126
+ ll_off = (FFI::TYPE_UINT64.alignment == 4? 4 : 8)
127
+ HashLayout.size.should == (ll_off + 8)
128
+ mp = FFI::MemoryPointer.new(HashLayout.size)
129
+ s = HashLayout.new mp
130
+ s[:a] = 0x12345678
131
+ mp.get_int(0).should == 0x12345678
132
+ s[:b] = 0xfee1deadbeef
133
+ mp.get_int64(ll_off).should == 0xfee1deadbeef
134
+ end
135
+ end
136
+ it "Can use Struct subclass as parameter type" do
137
+ module StructParam
138
+ extend FFI::Library
139
+ ffi_lib TestLibrary::PATH
140
+ class TestStruct < FFI::Struct
141
+ layout :c, :char
142
+ end
143
+ attach_function :struct_field_s8, [ TestStruct ], :char
144
+ end
145
+ end
146
+ it "Can use Struct subclass as IN parameter type" do
147
+ module StructParam
148
+ extend FFI::Library
149
+ ffi_lib TestLibrary::PATH
150
+ class TestStruct < FFI::Struct
151
+ layout :c, :char
152
+ end
153
+ attach_function :struct_field_s8, [ TestStruct.in ], :char
154
+ end
155
+ end
156
+ it "Can use Struct subclass as OUT parameter type" do
157
+ module StructParam
158
+ extend FFI::Library
159
+ ffi_lib TestLibrary::PATH
160
+ class TestStruct < FFI::Struct
161
+ layout :c, :char
162
+ end
163
+ attach_function :struct_field_s8, [ TestStruct.out ], :char
164
+ end
165
+ end
166
+ it "can be passed directly as a :pointer parameter" do
167
+ class TestStruct < FFI::Struct
168
+ layout :i, :int
169
+ end
170
+ s = TestStruct.new
171
+ s[:i] = 0x12
172
+ LibTest.ptr_ret_int32_t(s, 0).should == 0x12
173
+ end
174
+ it ":char member aligned correctly" do
175
+ class AlignChar < FFI::Struct
176
+ layout :c, :char, :v, :char
177
+ end
178
+ s = AlignChar.new
179
+ s[:v] = 0x12
180
+ LibTest.struct_align_s8(s.pointer).should == 0x12
181
+ end
182
+ it ":short member aligned correctly" do
183
+ class AlignShort < FFI::Struct
184
+ layout :c, :char, :v, :short
185
+ end
186
+ s = AlignShort.alloc_in
187
+ s[:v] = 0x1234
188
+ LibTest.struct_align_s16(s.pointer).should == 0x1234
189
+ end
190
+ it ":int member aligned correctly" do
191
+ class AlignInt < FFI::Struct
192
+ layout :c, :char, :v, :int
193
+ end
194
+ s = AlignInt.alloc_in
195
+ s[:v] = 0x12345678
196
+ LibTest.struct_align_s32(s.pointer).should == 0x12345678
197
+ end
198
+ it ":long_long member aligned correctly" do
199
+ class AlignLongLong < FFI::Struct
200
+ layout :c, :char, :v, :long_long
201
+ end
202
+ s = AlignLongLong.alloc_in
203
+ s[:v] = 0x123456789abcdef0
204
+ LibTest.struct_align_s64(s.pointer).should == 0x123456789abcdef0
205
+ end
206
+ it ":long member aligned correctly" do
207
+ class AlignLong < FFI::Struct
208
+ layout :c, :char, :v, :long
209
+ end
210
+ s = AlignLong.alloc_in
211
+ s[:v] = 0x12345678
212
+ LibTest.struct_align_long(s.pointer).should == 0x12345678
213
+ end
214
+ it ":float member aligned correctly" do
215
+ class AlignFloat < FFI::Struct
216
+ layout :c, :char, :v, :float
217
+ end
218
+ s = AlignFloat.alloc_in
219
+ s[:v] = 1.23456
220
+ (LibTest.struct_align_f32(s.pointer) - 1.23456).abs.should < 0.00001
221
+ end
222
+ it ":double member aligned correctly" do
223
+ class AlignDouble < FFI::Struct
224
+ layout :c, :char, :v, :double
225
+ end
226
+ s = AlignDouble.alloc_in
227
+ s[:v] = 1.23456789
228
+ (LibTest.struct_align_f64(s.pointer) - 1.23456789).abs.should < 0.00000001
229
+ end
230
+ it ":ulong, :pointer struct" do
231
+ class ULPStruct < FFI::Struct
232
+ layout :ul, :ulong, :p, :pointer
233
+ end
234
+ s = ULPStruct.alloc_in
235
+ s[:ul] = 0xdeadbeef
236
+ s[:p] = LibTest.ptr_from_address(0x12345678)
237
+ s.pointer.get_ulong(0).should == 0xdeadbeef
238
+ end
239
+ def test_num_field(type, v)
240
+ klass = Class.new(FFI::Struct)
241
+ klass.layout :v, type, :dummy, :long
242
+
243
+ s = klass.new
244
+ s[:v] = v
245
+ s.pointer.send("get_#{type.to_s}", 0).should == v
246
+ s.pointer.send("put_#{type.to_s}", 0, 0)
247
+ s[:v].should == 0
248
+ end
249
+ def self.int_field_test(type, values)
250
+ values.each do |v|
251
+ it "#{type} field r/w (#{v.to_s(16)})" do
252
+ test_num_field(type, v)
253
+ end
254
+ end
255
+ end
256
+ int_field_test(:char, [ 0, 127, -128, -1 ])
257
+ int_field_test(:uchar, [ 0, 0x7f, 0x80, 0xff ])
258
+ int_field_test(:short, [ 0, 0x7fff, -0x8000, -1 ])
259
+ int_field_test(:ushort, [ 0, 0x7fff, 0x8000, 0xffff ])
260
+ int_field_test(:int, [ 0, 0x7fffffff, -0x80000000, -1 ])
261
+ int_field_test(:uint, [ 0, 0x7fffffff, 0x80000000, 0xffffffff ])
262
+ int_field_test(:long_long, [ 0, 0x7fffffffffffffff, -0x8000000000000000, -1 ])
263
+ int_field_test(:ulong_long, [ 0, 0x7fffffffffffffff, 0x8000000000000000, 0xffffffffffffffff ])
264
+ if FFI::Platform::LONG_SIZE == 32
265
+ int_field_test(:long, [ 0, 0x7fffffff, -0x80000000, -1 ])
266
+ int_field_test(:ulong, [ 0, 0x7fffffff, 0x80000000, 0xffffffff ])
267
+ else
268
+ int_field_test(:long, [ 0, 0x7fffffffffffffff, -0x8000000000000000, -1 ])
269
+ int_field_test(:ulong, [ 0, 0x7fffffffffffffff, 0x8000000000000000, 0xffffffffffffffff ])
270
+ end
271
+ it ":float field r/w" do
272
+ klass = Class.new(FFI::Struct)
273
+ klass.layout :v, :float, :dummy, :long
274
+
275
+ s = klass.new
276
+ value = 1.23456
277
+ s[:v] = value
278
+ (s.pointer.get_float(0) - value).abs.should < 0.0001
279
+ end
280
+ it ":double field r/w" do
281
+ klass = Class.new(FFI::Struct)
282
+ klass.layout :v, :double, :dummy, :long
283
+
284
+ s = klass.new
285
+ value = 1.23456
286
+ s[:v] = value
287
+ (s.pointer.get_double(0) - value).abs.should < 0.0001
288
+ end
289
+ module CallbackMember
290
+ extend FFI::Library
291
+ ffi_lib TestLibrary::PATH
292
+ callback :add, [ :int, :int ], :int
293
+ callback :sub, [ :int, :int ], :int
294
+ class TestStruct < FFI::Struct
295
+ layout :add, :add,
296
+ :sub, :sub
297
+ end
298
+ attach_function :struct_call_add_cb, [TestStruct, :int, :int], :int
299
+ attach_function :struct_call_sub_cb, [TestStruct, :int, :int], :int
300
+ end
301
+ it "Can have CallbackInfo struct field" do
302
+ s = CallbackMember::TestStruct.new
303
+ add_proc = lambda { |a, b| a+b }
304
+ sub_proc = lambda { |a, b| a-b }
305
+ s[:add] = add_proc
306
+ s[:sub] = sub_proc
307
+ CallbackMember.struct_call_add_cb(s.pointer, 40, 2).should == 42
308
+ CallbackMember.struct_call_sub_cb(s.pointer, 44, 2).should == 42
309
+ end
310
+ it "Can return its members as a list" do
311
+ class TestStruct < FFI::Struct
312
+ layout :a, :int, :b, :int, :c, :int
313
+ end
314
+ TestStruct.members.should include(:a, :b, :c)
315
+ end
316
+ it "Can return its instance members and values as lists" do
317
+ class TestStruct < FFI::Struct
318
+ layout :a, :int, :b, :int, :c, :int
319
+ end
320
+ s = TestStruct.new
321
+ s.members.should include(:a, :b, :c)
322
+ s[:a] = 1
323
+ s[:b] = 2
324
+ s[:c] = 3
325
+ s.values.should include(1, 2, 3)
326
+ end
327
+ it 'should return an ordered field/offset pairs array' do
328
+ class TestStruct < FFI::Struct
329
+ layout :a, :int, :b, :int, :c, :int
330
+ end
331
+ s = TestStruct.new
332
+ s.offsets.should == [[:a, 0], [:b, 4], [:c, 8]]
333
+ TestStruct.offsets.should == [[:a, 0], [:b, 4], [:c, 8]]
334
+ end
335
+ it "Struct#offset_of returns offset of field within struct" do
336
+ class TestStruct < FFI::Struct
337
+ layout :a, :int, :b, :int, :c, :int
338
+ end
339
+ TestStruct.offset_of(:a).should == 0
340
+ TestStruct.offset_of(:b).should == 4
341
+ TestStruct.offset_of(:c).should == 8
342
+ end
343
+ end
344
+
345
+ describe FFI::Struct, ' with a nested struct field' do
346
+ module LibTest
347
+ extend FFI::Library
348
+ ffi_lib TestLibrary::PATH
349
+ class NestedStruct < FFI::Struct
350
+ layout :i, :int
351
+ end
352
+ class ContainerStruct < FFI::Struct
353
+ layout :first, :char, :ns, NestedStruct
354
+ end
355
+ attach_function :struct_align_nested_struct, [ :pointer ], :int
356
+ attach_function :struct_make_container_struct, [ :int ], :pointer
357
+ end
358
+ before do
359
+ @cs = LibTest::ContainerStruct.new
360
+ end
361
+ it 'should align correctly nested struct field' do
362
+ @cs[:ns][:i] = 123
363
+ LibTest.struct_align_nested_struct(@cs.to_ptr).should == 123
364
+ end
365
+ it 'should correctly calculate Container size (in bytes)' do
366
+ LibTest::ContainerStruct.size.should == 8
367
+ end
368
+ it 'should return a Struct object when the field is accessed' do
369
+ @cs[:ns].is_a?(FFI::Struct).should be_true
370
+ end
371
+ it 'should read a value from memory' do
372
+ @cs = LibTest::ContainerStruct.new(LibTest.struct_make_container_struct(123))
373
+ @cs[:ns][:i].should == 123
374
+ end
375
+ it 'should write a value to memory' do
376
+ @cs = LibTest::ContainerStruct.new(LibTest.struct_make_container_struct(123))
377
+ @cs[:ns][:i] = 456
378
+ LibTest.struct_align_nested_struct(@cs.to_ptr).should == 456
379
+ end
380
+ end
381
+
382
+ describe FFI::Struct, ' by value' do
383
+ module LibTest
384
+ extend FFI::Library
385
+ ffi_lib TestLibrary::PATH
386
+
387
+ class S8S32 < FFI::Struct
388
+ layout :s8, :char, :s32, :int
389
+ end
390
+ attach_function :struct_return_s8s32, [ ], S8S32.by_value
391
+ attach_function :struct_s8s32_set, [ :char, :int ], S8S32.by_value
392
+ attach_function :struct_s8s32_get_s8, [ S8S32.by_value ], :char
393
+ attach_function :struct_s8s32_get_s32, [ S8S32.by_value ], :int
394
+ attach_function :struct_s8s32_s32_ret_s32, [ S8S32.by_value, :int ], :int
395
+ attach_function :struct_s8s32_s64_ret_s64, [ S8S32.by_value, :long_long ], :long_long
396
+ end
397
+
398
+ it 'return using pre-set values' do
399
+ s = LibTest.struct_return_s8s32
400
+ s[:s8].should == 0x7f
401
+ s[:s32].should == 0x12345678
402
+ end
403
+
404
+ it 'return using passed in values' do
405
+ s = LibTest.struct_s8s32_set(123, 456789)
406
+ s[:s8].should == 123
407
+ s[:s32].should == 456789
408
+ end
409
+
410
+ it 'parameter' do
411
+ s = LibTest::S8S32.new
412
+ s[:s8] = 0x12
413
+ s[:s32] = 0x34567890
414
+ LibTest.struct_s8s32_get_s8(s).should == 0x12
415
+ LibTest.struct_s8s32_get_s32(s).should == 0x34567890
416
+ end
417
+
418
+ it 'parameter with following s32' do
419
+ s = LibTest::S8S32.new
420
+ s[:s8] = 0x12
421
+ s[:s32] = 0x34567890
422
+
423
+ LibTest.struct_s8s32_s32_ret_s32(s, 0x1eefdead).should == 0x1eefdead
424
+ end
425
+
426
+ it 'parameter with following s64' do
427
+ s = LibTest::S8S32.new
428
+ s[:s8] = 0x12
429
+ s[:s32] = 0x34567890
430
+
431
+ LibTest.struct_s8s32_s64_ret_s64(s, 0xdeadcafebabe).should == 0xdeadcafebabe
432
+ end
433
+ end
434
+
435
+ describe FFI::Struct, ' with an array field' do
436
+ module LibTest
437
+ extend FFI::Library
438
+ ffi_lib TestLibrary::PATH
439
+ class StructWithArray < FFI::Struct
440
+ layout :first, :char, :a, [:int, 5]
441
+ end
442
+ attach_function :struct_make_struct_with_array, [:int, :int, :int, :int, :int], :pointer
443
+ attach_function :struct_field_array, [:pointer], :pointer
444
+ end
445
+ before do
446
+ @s = LibTest::StructWithArray.new
447
+ end
448
+ it 'should correctly calculate StructWithArray size (in bytes)' do
449
+ LibTest::StructWithArray.size.should == 24
450
+ end
451
+ it 'should read values from memory' do
452
+ @s = LibTest::StructWithArray.new(LibTest.struct_make_struct_with_array(0, 1, 2, 3, 4))
453
+ @s[:a].to_a.should == [0, 1, 2, 3, 4]
454
+ end
455
+ # it 'should cache array object for successive calls' do
456
+ # @s[:a].object_id.should == @s[:a].object_id
457
+ # end
458
+ it 'should return the size of the array field in bytes' do
459
+ @s = LibTest::StructWithArray.new(LibTest.struct_make_struct_with_array(0, 1, 2, 3, 4))
460
+ @s[:a].size.should == 20
461
+ end
462
+ it 'should allow iteration through the array elements' do
463
+ @s = LibTest::StructWithArray.new(LibTest.struct_make_struct_with_array(0, 1, 2, 3, 4))
464
+ @s[:a].each_with_index { |elem, i| elem.should == i }
465
+ end
466
+ it 'should return the pointer to the array' do
467
+ @s = LibTest::StructWithArray.new(LibTest.struct_make_struct_with_array(0, 1, 2, 3, 4))
468
+ @s[:a].to_ptr.should == LibTest::struct_field_array(@s.to_ptr)
469
+ end
470
+ end
471
+
472
+ describe 'BuggedStruct' do
473
+ module LibTest
474
+ extend FFI::Library
475
+ ffi_lib TestLibrary::PATH
476
+ class BuggedStruct < FFI::Struct
477
+ layout :visible, :uchar,
478
+ :x, :uint,
479
+ :y, :uint,
480
+ :rx, :short,
481
+ :ry, :short,
482
+ :order, :uchar,
483
+ :size, :uchar
484
+ end
485
+ attach_function :bugged_struct_size, [], :uint
486
+ end
487
+ it 'should return its correct size' do
488
+ LibTest::BuggedStruct.size.should == LibTest.bugged_struct_size
489
+ end
490
+ it "offsets within struct should be correct" do
491
+ LibTest::BuggedStruct.offset_of(:visible).should == 0
492
+ LibTest::BuggedStruct.offset_of(:x).should == 4
493
+ LibTest::BuggedStruct.offset_of(:y).should == 8
494
+ LibTest::BuggedStruct.offset_of(:rx).should == 12
495
+ LibTest::BuggedStruct.offset_of(:ry).should == 14
496
+ LibTest::BuggedStruct.offset_of(:order).should == 16
497
+ LibTest::BuggedStruct.offset_of(:size).should == 17
498
+ end
499
+ it 'should return correct field/offset pairs' do
500
+ LibTest::BuggedStruct.offsets.sort do |a, b|
501
+ a[1] <=> b[1]
502
+ end.should == [[:visible, 0], [:x, 4], [:y, 8], [:rx, 12], [:ry, 14], [:order, 16], [:size, 17]]
503
+ end
504
+ end
505
+
506
+ describe "Struct allocation" do
507
+ it "MemoryPointer.new(Struct, 2)" do
508
+ class S < FFI::Struct
509
+ layout :i, :uint
510
+ end
511
+ p = FFI::MemoryPointer.new(S, 2)
512
+ p.total.should == 8
513
+ p.type_size.should == 4
514
+ p.put_uint(4, 0xdeadbeef)
515
+ S.new(p[1])[:i].should == 0xdeadbeef
516
+ p[1].address.should == (p[0].address + 4)
517
+ end
518
+
519
+ it "Buffer.new(Struct, 2)" do
520
+ class S < FFI::Struct
521
+ layout :i, :uint
522
+ end
523
+ p = FFI::Buffer.new(S, 2)
524
+ p.total.should == 8
525
+ p.type_size.should == 4
526
+ p.put_uint(4, 0xdeadbeef)
527
+ S.new(p[1])[:i].should == 0xdeadbeef
528
+ end
529
+ end