ffi 1.9.3-x64-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 (436) hide show
  1. data/COPYING +49 -0
  2. data/LICENSE +24 -0
  3. data/README.md +109 -0
  4. data/Rakefile +220 -0
  5. data/ext/ffi_c/AbstractMemory.c +1032 -0
  6. data/ext/ffi_c/AbstractMemory.h +175 -0
  7. data/ext/ffi_c/ArrayType.c +162 -0
  8. data/ext/ffi_c/ArrayType.h +59 -0
  9. data/ext/ffi_c/Buffer.c +365 -0
  10. data/ext/ffi_c/Call.c +465 -0
  11. data/ext/ffi_c/Call.h +93 -0
  12. data/ext/ffi_c/ClosurePool.c +283 -0
  13. data/ext/ffi_c/ClosurePool.h +57 -0
  14. data/ext/ffi_c/DataConverter.c +91 -0
  15. data/ext/ffi_c/DynamicLibrary.c +333 -0
  16. data/ext/ffi_c/DynamicLibrary.h +49 -0
  17. data/ext/ffi_c/Function.c +999 -0
  18. data/ext/ffi_c/Function.h +87 -0
  19. data/ext/ffi_c/FunctionInfo.c +271 -0
  20. data/ext/ffi_c/LastError.c +184 -0
  21. data/ext/ffi_c/LastError.h +47 -0
  22. data/ext/ffi_c/LongDouble.c +63 -0
  23. data/ext/ffi_c/LongDouble.h +51 -0
  24. data/ext/ffi_c/MappedType.c +168 -0
  25. data/ext/ffi_c/MappedType.h +59 -0
  26. data/ext/ffi_c/MemoryPointer.c +197 -0
  27. data/ext/ffi_c/MemoryPointer.h +53 -0
  28. data/ext/ffi_c/MethodHandle.c +360 -0
  29. data/ext/ffi_c/MethodHandle.h +55 -0
  30. data/ext/ffi_c/Platform.c +121 -0
  31. data/ext/ffi_c/Platform.h +45 -0
  32. data/ext/ffi_c/Pointer.c +508 -0
  33. data/ext/ffi_c/Pointer.h +63 -0
  34. data/ext/ffi_c/Struct.c +828 -0
  35. data/ext/ffi_c/Struct.h +106 -0
  36. data/ext/ffi_c/StructByReference.c +190 -0
  37. data/ext/ffi_c/StructByReference.h +50 -0
  38. data/ext/ffi_c/StructByValue.c +150 -0
  39. data/ext/ffi_c/StructByValue.h +55 -0
  40. data/ext/ffi_c/StructLayout.c +698 -0
  41. data/ext/ffi_c/Thread.c +352 -0
  42. data/ext/ffi_c/Thread.h +95 -0
  43. data/ext/ffi_c/Type.c +397 -0
  44. data/ext/ffi_c/Type.h +62 -0
  45. data/ext/ffi_c/Types.c +139 -0
  46. data/ext/ffi_c/Types.h +89 -0
  47. data/ext/ffi_c/Variadic.c +276 -0
  48. data/ext/ffi_c/compat.h +83 -0
  49. data/ext/ffi_c/extconf.rb +64 -0
  50. data/ext/ffi_c/ffi.c +98 -0
  51. data/ext/ffi_c/libffi.bsd.mk +34 -0
  52. data/ext/ffi_c/libffi.darwin.mk +95 -0
  53. data/ext/ffi_c/libffi.gnu.mk +31 -0
  54. data/ext/ffi_c/libffi.mk +13 -0
  55. data/ext/ffi_c/libffi.vc.mk +26 -0
  56. data/ext/ffi_c/libffi.vc64.mk +26 -0
  57. data/ext/ffi_c/libffi/ChangeLog +4600 -0
  58. data/ext/ffi_c/libffi/ChangeLog.libffi +584 -0
  59. data/ext/ffi_c/libffi/ChangeLog.libgcj +40 -0
  60. data/ext/ffi_c/libffi/ChangeLog.v1 +764 -0
  61. data/ext/ffi_c/libffi/LICENSE +21 -0
  62. data/ext/ffi_c/libffi/Makefile.am +196 -0
  63. data/ext/ffi_c/libffi/Makefile.in +1820 -0
  64. data/ext/ffi_c/libffi/Makefile.vc +141 -0
  65. data/ext/ffi_c/libffi/Makefile.vc64 +141 -0
  66. data/ext/ffi_c/libffi/README +342 -0
  67. data/ext/ffi_c/libffi/acinclude.m4 +92 -0
  68. data/ext/ffi_c/libffi/aclocal.m4 +1873 -0
  69. data/ext/ffi_c/libffi/build-ios.sh +67 -0
  70. data/ext/ffi_c/libffi/compile +143 -0
  71. data/ext/ffi_c/libffi/config.guess +1501 -0
  72. data/ext/ffi_c/libffi/config.sub +1705 -0
  73. data/ext/ffi_c/libffi/configure +17191 -0
  74. data/ext/ffi_c/libffi/configure.ac +496 -0
  75. data/ext/ffi_c/libffi/configure.host +11 -0
  76. data/ext/ffi_c/libffi/depcomp +630 -0
  77. data/ext/ffi_c/libffi/doc/libffi.info +593 -0
  78. data/ext/ffi_c/libffi/doc/libffi.texi +600 -0
  79. data/ext/ffi_c/libffi/doc/stamp-vti +4 -0
  80. data/ext/ffi_c/libffi/doc/version.texi +4 -0
  81. data/ext/ffi_c/libffi/fficonfig.h.in +199 -0
  82. data/ext/ffi_c/libffi/fficonfig.hw +57 -0
  83. data/ext/ffi_c/libffi/include/Makefile.am +9 -0
  84. data/ext/ffi_c/libffi/include/Makefile.in +487 -0
  85. data/ext/ffi_c/libffi/include/ffi.h.in +427 -0
  86. data/ext/ffi_c/libffi/include/ffi.h.vc +427 -0
  87. data/ext/ffi_c/libffi/include/ffi.h.vc64 +427 -0
  88. data/ext/ffi_c/libffi/include/ffi_common.h +126 -0
  89. data/ext/ffi_c/libffi/install-sh +520 -0
  90. data/ext/ffi_c/libffi/libffi.pc.in +10 -0
  91. data/ext/ffi_c/libffi/libtool-version +29 -0
  92. data/ext/ffi_c/libffi/ltmain.sh +9636 -0
  93. data/ext/ffi_c/libffi/m4/ax_cc_maxopt.m4 +176 -0
  94. data/ext/ffi_c/libffi/m4/ax_cflags_warn_all.m4 +195 -0
  95. data/ext/ffi_c/libffi/m4/ax_check_compiler_flags.m4 +76 -0
  96. data/ext/ffi_c/libffi/m4/ax_compiler_vendor.m4 +63 -0
  97. data/ext/ffi_c/libffi/m4/ax_configure_args.m4 +70 -0
  98. data/ext/ffi_c/libffi/m4/ax_enable_builddir.m4 +300 -0
  99. data/ext/ffi_c/libffi/m4/ax_gcc_archflag.m4 +215 -0
  100. data/ext/ffi_c/libffi/m4/ax_gcc_x86_cpuid.m4 +79 -0
  101. data/ext/ffi_c/libffi/m4/libtool.m4 +7831 -0
  102. data/ext/ffi_c/libffi/m4/ltoptions.m4 +369 -0
  103. data/ext/ffi_c/libffi/m4/ltsugar.m4 +123 -0
  104. data/ext/ffi_c/libffi/m4/ltversion.m4 +23 -0
  105. data/ext/ffi_c/libffi/m4/lt~obsolete.m4 +98 -0
  106. data/ext/ffi_c/libffi/man/Makefile.am +8 -0
  107. data/ext/ffi_c/libffi/man/Makefile.in +466 -0
  108. data/ext/ffi_c/libffi/man/ffi.3 +31 -0
  109. data/ext/ffi_c/libffi/man/ffi_call.3 +103 -0
  110. data/ext/ffi_c/libffi/man/ffi_prep_cif.3 +66 -0
  111. data/ext/ffi_c/libffi/mdate-sh +201 -0
  112. data/ext/ffi_c/libffi/missing +376 -0
  113. data/ext/ffi_c/libffi/msvcc.sh +197 -0
  114. data/ext/ffi_c/libffi/src/alpha/ffi.c +284 -0
  115. data/ext/ffi_c/libffi/src/alpha/ffitarget.h +48 -0
  116. data/ext/ffi_c/libffi/src/alpha/osf.S +387 -0
  117. data/ext/ffi_c/libffi/src/arm/ffi.c +728 -0
  118. data/ext/ffi_c/libffi/src/arm/ffitarget.h +65 -0
  119. data/ext/ffi_c/libffi/src/arm/gentramp.sh +118 -0
  120. data/ext/ffi_c/libffi/src/arm/sysv.S +497 -0
  121. data/ext/ffi_c/libffi/src/arm/trampoline.S +4450 -0
  122. data/ext/ffi_c/libffi/src/avr32/ffi.c +423 -0
  123. data/ext/ffi_c/libffi/src/avr32/ffitarget.h +50 -0
  124. data/ext/ffi_c/libffi/src/avr32/sysv.S +208 -0
  125. data/ext/ffi_c/libffi/src/closures.c +615 -0
  126. data/ext/ffi_c/libffi/src/cris/ffi.c +383 -0
  127. data/ext/ffi_c/libffi/src/cris/ffitarget.h +51 -0
  128. data/ext/ffi_c/libffi/src/cris/sysv.S +215 -0
  129. data/ext/ffi_c/libffi/src/debug.c +59 -0
  130. data/ext/ffi_c/libffi/src/dlmalloc.c +5161 -0
  131. data/ext/ffi_c/libffi/src/frv/eabi.S +128 -0
  132. data/ext/ffi_c/libffi/src/frv/ffi.c +292 -0
  133. data/ext/ffi_c/libffi/src/frv/ffitarget.h +57 -0
  134. data/ext/ffi_c/libffi/src/ia64/ffi.c +582 -0
  135. data/ext/ffi_c/libffi/src/ia64/ffitarget.h +50 -0
  136. data/ext/ffi_c/libffi/src/ia64/ia64_flags.h +40 -0
  137. data/ext/ffi_c/libffi/src/ia64/unix.S +560 -0
  138. data/ext/ffi_c/libffi/src/java_raw_api.c +356 -0
  139. data/ext/ffi_c/libffi/src/m32r/ffi.c +232 -0
  140. data/ext/ffi_c/libffi/src/m32r/ffitarget.h +48 -0
  141. data/ext/ffi_c/libffi/src/m32r/sysv.S +121 -0
  142. data/ext/ffi_c/libffi/src/m68k/ffi.c +288 -0
  143. data/ext/ffi_c/libffi/src/m68k/ffitarget.h +49 -0
  144. data/ext/ffi_c/libffi/src/m68k/sysv.S +270 -0
  145. data/ext/ffi_c/libffi/src/mips/ffi.c +1036 -0
  146. data/ext/ffi_c/libffi/src/mips/ffitarget.h +242 -0
  147. data/ext/ffi_c/libffi/src/mips/n32.S +591 -0
  148. data/ext/ffi_c/libffi/src/mips/o32.S +381 -0
  149. data/ext/ffi_c/libffi/src/moxie/eabi.S +128 -0
  150. data/ext/ffi_c/libffi/src/moxie/ffi.c +276 -0
  151. data/ext/ffi_c/libffi/src/pa/ffi.c +719 -0
  152. data/ext/ffi_c/libffi/src/pa/ffitarget.h +78 -0
  153. data/ext/ffi_c/libffi/src/pa/hpux32.S +368 -0
  154. data/ext/ffi_c/libffi/src/pa/linux.S +357 -0
  155. data/ext/ffi_c/libffi/src/powerpc/aix.S +328 -0
  156. data/ext/ffi_c/libffi/src/powerpc/aix_closure.S +445 -0
  157. data/ext/ffi_c/libffi/src/powerpc/asm.h +125 -0
  158. data/ext/ffi_c/libffi/src/powerpc/darwin.S +383 -0
  159. data/ext/ffi_c/libffi/src/powerpc/darwin_closure.S +575 -0
  160. data/ext/ffi_c/libffi/src/powerpc/ffi.c +1448 -0
  161. data/ext/ffi_c/libffi/src/powerpc/ffi_darwin.c +1359 -0
  162. data/ext/ffi_c/libffi/src/powerpc/ffitarget.h +139 -0
  163. data/ext/ffi_c/libffi/src/powerpc/linux64.S +187 -0
  164. data/ext/ffi_c/libffi/src/powerpc/linux64_closure.S +236 -0
  165. data/ext/ffi_c/libffi/src/powerpc/ppc_closure.S +327 -0
  166. data/ext/ffi_c/libffi/src/powerpc/sysv.S +219 -0
  167. data/ext/ffi_c/libffi/src/prep_cif.c +177 -0
  168. data/ext/ffi_c/libffi/src/raw_api.c +254 -0
  169. data/ext/ffi_c/libffi/src/s390/ffi.c +780 -0
  170. data/ext/ffi_c/libffi/src/s390/ffitarget.h +62 -0
  171. data/ext/ffi_c/libffi/src/s390/sysv.S +434 -0
  172. data/ext/ffi_c/libffi/src/sh/ffi.c +716 -0
  173. data/ext/ffi_c/libffi/src/sh/ffitarget.h +49 -0
  174. data/ext/ffi_c/libffi/src/sh/sysv.S +850 -0
  175. data/ext/ffi_c/libffi/src/sh64/ffi.c +468 -0
  176. data/ext/ffi_c/libffi/src/sh64/ffitarget.h +53 -0
  177. data/ext/ffi_c/libffi/src/sh64/sysv.S +539 -0
  178. data/ext/ffi_c/libffi/src/sparc/ffi.c +669 -0
  179. data/ext/ffi_c/libffi/src/sparc/ffitarget.h +68 -0
  180. data/ext/ffi_c/libffi/src/sparc/v8.S +313 -0
  181. data/ext/ffi_c/libffi/src/sparc/v9.S +307 -0
  182. data/ext/ffi_c/libffi/src/types.c +77 -0
  183. data/ext/ffi_c/libffi/src/x86/darwin.S +444 -0
  184. data/ext/ffi_c/libffi/src/x86/darwin64.S +416 -0
  185. data/ext/ffi_c/libffi/src/x86/ffi.c +644 -0
  186. data/ext/ffi_c/libffi/src/x86/ffi64.c +635 -0
  187. data/ext/ffi_c/libffi/src/x86/ffitarget.h +121 -0
  188. data/ext/ffi_c/libffi/src/x86/freebsd.S +458 -0
  189. data/ext/ffi_c/libffi/src/x86/sysv.S +468 -0
  190. data/ext/ffi_c/libffi/src/x86/unix64.S +426 -0
  191. data/ext/ffi_c/libffi/src/x86/win32.S +1065 -0
  192. data/ext/ffi_c/libffi/src/x86/win64.S +468 -0
  193. data/ext/ffi_c/libffi/testsuite/Makefile.am +80 -0
  194. data/ext/ffi_c/libffi/testsuite/Makefile.in +500 -0
  195. data/ext/ffi_c/libffi/testsuite/config/default.exp +1 -0
  196. data/ext/ffi_c/libffi/testsuite/lib/libffi-dg.exp +300 -0
  197. data/ext/ffi_c/libffi/testsuite/lib/libffi.exp +350 -0
  198. data/ext/ffi_c/libffi/testsuite/lib/target-libpath.exp +263 -0
  199. data/ext/ffi_c/libffi/testsuite/lib/wrapper.exp +45 -0
  200. data/ext/ffi_c/libffi/testsuite/libffi.call/call.exp +32 -0
  201. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn0.c +89 -0
  202. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn1.c +81 -0
  203. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn2.c +81 -0
  204. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn3.c +82 -0
  205. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn4.c +89 -0
  206. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn5.c +92 -0
  207. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn6.c +90 -0
  208. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_loc_fn0.c +95 -0
  209. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_stdcall.c +64 -0
  210. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_12byte.c +94 -0
  211. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_16byte.c +95 -0
  212. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_18byte.c +96 -0
  213. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_19byte.c +102 -0
  214. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_1_1byte.c +89 -0
  215. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_20byte.c +91 -0
  216. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_20byte1.c +93 -0
  217. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_24byte.c +113 -0
  218. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_2byte.c +90 -0
  219. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3_1byte.c +95 -0
  220. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3byte1.c +90 -0
  221. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3byte2.c +90 -0
  222. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_4_1byte.c +98 -0
  223. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_4byte.c +90 -0
  224. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_5_1_byte.c +109 -0
  225. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_5byte.c +98 -0
  226. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_64byte.c +124 -0
  227. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_6_1_byte.c +113 -0
  228. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_6byte.c +99 -0
  229. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_7_1_byte.c +117 -0
  230. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_7byte.c +97 -0
  231. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_8byte.c +88 -0
  232. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_9byte1.c +90 -0
  233. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_9byte2.c +91 -0
  234. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_double.c +93 -0
  235. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_float.c +91 -0
  236. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble.c +92 -0
  237. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble_split.c +134 -0
  238. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble_split2.c +117 -0
  239. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_pointer.c +95 -0
  240. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint16.c +91 -0
  241. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint32.c +91 -0
  242. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint64.c +92 -0
  243. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint16.c +91 -0
  244. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint32.c +91 -0
  245. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint64.c +93 -0
  246. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_dbls_struct.c +66 -0
  247. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_double.c +43 -0
  248. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_double_va.c +60 -0
  249. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_float.c +42 -0
  250. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_longdouble.c +105 -0
  251. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_longdouble_va.c +60 -0
  252. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_schar.c +74 -0
  253. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_sshort.c +74 -0
  254. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_sshortchar.c +86 -0
  255. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_uchar.c +91 -0
  256. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_ushort.c +74 -0
  257. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_ushortchar.c +86 -0
  258. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_pointer.c +74 -0
  259. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_pointer_stack.c +140 -0
  260. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_schar.c +44 -0
  261. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_sint.c +42 -0
  262. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_sshort.c +42 -0
  263. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uchar.c +42 -0
  264. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uint.c +43 -0
  265. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ulonglong.c +47 -0
  266. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ushort.c +43 -0
  267. data/ext/ffi_c/libffi/testsuite/libffi.call/err_bad_abi.c +36 -0
  268. data/ext/ffi_c/libffi/testsuite/libffi.call/err_bad_typedef.c +26 -0
  269. data/ext/ffi_c/libffi/testsuite/libffi.call/ffitest.h +153 -0
  270. data/ext/ffi_c/libffi/testsuite/libffi.call/float.c +59 -0
  271. data/ext/ffi_c/libffi/testsuite/libffi.call/float1.c +58 -0
  272. data/ext/ffi_c/libffi/testsuite/libffi.call/float2.c +58 -0
  273. data/ext/ffi_c/libffi/testsuite/libffi.call/float3.c +72 -0
  274. data/ext/ffi_c/libffi/testsuite/libffi.call/float4.c +62 -0
  275. data/ext/ffi_c/libffi/testsuite/libffi.call/huge_struct.c +342 -0
  276. data/ext/ffi_c/libffi/testsuite/libffi.call/many.c +69 -0
  277. data/ext/ffi_c/libffi/testsuite/libffi.call/many_win32.c +63 -0
  278. data/ext/ffi_c/libffi/testsuite/libffi.call/negint.c +53 -0
  279. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct.c +152 -0
  280. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct1.c +161 -0
  281. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct10.c +133 -0
  282. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct2.c +110 -0
  283. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct3.c +111 -0
  284. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct4.c +111 -0
  285. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct5.c +112 -0
  286. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct6.c +131 -0
  287. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct7.c +111 -0
  288. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct8.c +131 -0
  289. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct9.c +131 -0
  290. data/ext/ffi_c/libffi/testsuite/libffi.call/problem1.c +90 -0
  291. data/ext/ffi_c/libffi/testsuite/libffi.call/promotion.c +59 -0
  292. data/ext/ffi_c/libffi/testsuite/libffi.call/pyobjc-tc.c +114 -0
  293. data/ext/ffi_c/libffi/testsuite/libffi.call/return_dbl.c +35 -0
  294. data/ext/ffi_c/libffi/testsuite/libffi.call/return_dbl1.c +43 -0
  295. data/ext/ffi_c/libffi/testsuite/libffi.call/return_dbl2.c +42 -0
  296. data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl.c +35 -0
  297. data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl1.c +36 -0
  298. data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl2.c +49 -0
  299. data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl3.c +42 -0
  300. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ldl.c +34 -0
  301. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ll.c +41 -0
  302. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ll1.c +43 -0
  303. data/ext/ffi_c/libffi/testsuite/libffi.call/return_sc.c +36 -0
  304. data/ext/ffi_c/libffi/testsuite/libffi.call/return_sl.c +38 -0
  305. data/ext/ffi_c/libffi/testsuite/libffi.call/return_uc.c +38 -0
  306. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ul.c +38 -0
  307. data/ext/ffi_c/libffi/testsuite/libffi.call/stret_large.c +145 -0
  308. data/ext/ffi_c/libffi/testsuite/libffi.call/stret_large2.c +148 -0
  309. data/ext/ffi_c/libffi/testsuite/libffi.call/stret_medium.c +124 -0
  310. data/ext/ffi_c/libffi/testsuite/libffi.call/stret_medium2.c +125 -0
  311. data/ext/ffi_c/libffi/testsuite/libffi.call/strlen.c +44 -0
  312. data/ext/ffi_c/libffi/testsuite/libffi.call/strlen_win32.c +44 -0
  313. data/ext/ffi_c/libffi/testsuite/libffi.call/struct1.c +65 -0
  314. data/ext/ffi_c/libffi/testsuite/libffi.call/struct2.c +67 -0
  315. data/ext/ffi_c/libffi/testsuite/libffi.call/struct3.c +59 -0
  316. data/ext/ffi_c/libffi/testsuite/libffi.call/struct4.c +63 -0
  317. data/ext/ffi_c/libffi/testsuite/libffi.call/struct5.c +65 -0
  318. data/ext/ffi_c/libffi/testsuite/libffi.call/struct6.c +64 -0
  319. data/ext/ffi_c/libffi/testsuite/libffi.call/struct7.c +74 -0
  320. data/ext/ffi_c/libffi/testsuite/libffi.call/struct8.c +80 -0
  321. data/ext/ffi_c/libffi/testsuite/libffi.call/struct9.c +67 -0
  322. data/ext/ffi_c/libffi/testsuite/libffi.call/testclosure.c +70 -0
  323. data/ext/ffi_c/libffi/testsuite/libffi.special/ffitestcxx.h +96 -0
  324. data/ext/ffi_c/libffi/testsuite/libffi.special/special.exp +35 -0
  325. data/ext/ffi_c/libffi/testsuite/libffi.special/unwindtest.cc +124 -0
  326. data/ext/ffi_c/libffi/testsuite/libffi.special/unwindtest_ffi_call.cc +53 -0
  327. data/ext/ffi_c/libffi/texinfo.tex +7210 -0
  328. data/ext/ffi_c/rbffi.h +57 -0
  329. data/ext/ffi_c/rbffi_endian.h +59 -0
  330. data/ext/ffi_c/win32/stdbool.h +8 -0
  331. data/ext/ffi_c/win32/stdint.h +201 -0
  332. data/ffi.gemspec +22 -0
  333. data/gen/Rakefile +30 -0
  334. data/lib/ffi.rb +28 -0
  335. data/lib/ffi/autopointer.rb +194 -0
  336. data/lib/ffi/buffer.rb +4 -0
  337. data/lib/ffi/callback.rb +4 -0
  338. data/lib/ffi/enum.rb +173 -0
  339. data/lib/ffi/errno.rb +43 -0
  340. data/lib/ffi/ffi.rb +44 -0
  341. data/lib/ffi/io.rb +62 -0
  342. data/lib/ffi/library.rb +499 -0
  343. data/lib/ffi/managedstruct.rb +84 -0
  344. data/lib/ffi/memorypointer.rb +1 -0
  345. data/lib/ffi/platform.rb +148 -0
  346. data/lib/ffi/platform/arm-linux/types.conf +104 -0
  347. data/lib/ffi/platform/i386-cygwin/types.conf +3 -0
  348. data/lib/ffi/platform/i386-darwin/types.conf +100 -0
  349. data/lib/ffi/platform/i386-freebsd/types.conf +152 -0
  350. data/lib/ffi/platform/i386-gnu/types.conf +107 -0
  351. data/lib/ffi/platform/i386-linux/types.conf +103 -0
  352. data/lib/ffi/platform/i386-netbsd/types.conf +126 -0
  353. data/lib/ffi/platform/i386-openbsd/types.conf +128 -0
  354. data/lib/ffi/platform/i386-solaris/types.conf +122 -0
  355. data/lib/ffi/platform/i386-windows/types.conf +105 -0
  356. data/lib/ffi/platform/ia64-linux/types.conf +104 -0
  357. data/lib/ffi/platform/mips-linux/types.conf +102 -0
  358. data/lib/ffi/platform/mipsel-linux/types.conf +102 -0
  359. data/lib/ffi/platform/powerpc-aix/types.conf +180 -0
  360. data/lib/ffi/platform/powerpc-darwin/types.conf +100 -0
  361. data/lib/ffi/platform/powerpc-linux/types.conf +100 -0
  362. data/lib/ffi/platform/s390-linux/types.conf +102 -0
  363. data/lib/ffi/platform/s390x-linux/types.conf +102 -0
  364. data/lib/ffi/platform/sparc-linux/types.conf +102 -0
  365. data/lib/ffi/platform/sparc-solaris/types.conf +128 -0
  366. data/lib/ffi/platform/sparcv9-solaris/types.conf +128 -0
  367. data/lib/ffi/platform/x86_64-cygwin/types.conf +3 -0
  368. data/lib/ffi/platform/x86_64-darwin/types.conf +100 -0
  369. data/lib/ffi/platform/x86_64-freebsd/types.conf +128 -0
  370. data/lib/ffi/platform/x86_64-linux/types.conf +102 -0
  371. data/lib/ffi/platform/x86_64-netbsd/types.conf +126 -0
  372. data/lib/ffi/platform/x86_64-openbsd/types.conf +128 -0
  373. data/lib/ffi/platform/x86_64-solaris/types.conf +122 -0
  374. data/lib/ffi/platform/x86_64-windows/types.conf +27 -0
  375. data/lib/ffi/pointer.rb +134 -0
  376. data/lib/ffi/struct.rb +367 -0
  377. data/lib/ffi/struct_layout_builder.rb +222 -0
  378. data/lib/ffi/tools/const_generator.rb +229 -0
  379. data/lib/ffi/tools/generator.rb +60 -0
  380. data/lib/ffi/tools/generator_task.rb +36 -0
  381. data/lib/ffi/tools/struct_generator.rb +194 -0
  382. data/lib/ffi/tools/types_generator.rb +135 -0
  383. data/lib/ffi/types.rb +190 -0
  384. data/lib/ffi/union.rb +43 -0
  385. data/lib/ffi/variadic.rb +78 -0
  386. data/lib/ffi/version.rb +4 -0
  387. data/lib/ffi_c.so +0 -0
  388. data/libtest/Benchmark.c +52 -0
  389. data/libtest/BoolTest.c +34 -0
  390. data/libtest/BufferTest.c +31 -0
  391. data/libtest/ClosureTest.c +190 -0
  392. data/libtest/EnumTest.c +34 -0
  393. data/libtest/FunctionTest.c +58 -0
  394. data/libtest/GNUmakefile +149 -0
  395. data/libtest/GlobalVariable.c +62 -0
  396. data/libtest/LastErrorTest.c +21 -0
  397. data/libtest/NumberTest.c +132 -0
  398. data/libtest/PointerTest.c +63 -0
  399. data/libtest/ReferenceTest.c +23 -0
  400. data/libtest/StringTest.c +34 -0
  401. data/libtest/StructTest.c +243 -0
  402. data/libtest/UnionTest.c +43 -0
  403. data/libtest/VariadicTest.c +62 -0
  404. data/spec/ffi/async_callback_spec.rb +35 -0
  405. data/spec/ffi/bool_spec.rb +29 -0
  406. data/spec/ffi/buffer_spec.rb +251 -0
  407. data/spec/ffi/callback_spec.rb +667 -0
  408. data/spec/ffi/custom_param_type.rb +36 -0
  409. data/spec/ffi/custom_type_spec.rb +74 -0
  410. data/spec/ffi/dup_spec.rb +54 -0
  411. data/spec/ffi/enum_spec.rb +220 -0
  412. data/spec/ffi/errno_spec.rb +18 -0
  413. data/spec/ffi/ffi_spec.rb +29 -0
  414. data/spec/ffi/function_spec.rb +76 -0
  415. data/spec/ffi/library_spec.rb +216 -0
  416. data/spec/ffi/long_double.rb +30 -0
  417. data/spec/ffi/managed_struct_spec.rb +57 -0
  418. data/spec/ffi/number_spec.rb +236 -0
  419. data/spec/ffi/pointer_spec.rb +265 -0
  420. data/spec/ffi/rbx/attach_function_spec.rb +28 -0
  421. data/spec/ffi/rbx/memory_pointer_spec.rb +123 -0
  422. data/spec/ffi/rbx/spec_helper.rb +1 -0
  423. data/spec/ffi/rbx/struct_spec.rb +13 -0
  424. data/spec/ffi/spec_helper.rb +33 -0
  425. data/spec/ffi/string_spec.rb +108 -0
  426. data/spec/ffi/strptr_spec.rb +50 -0
  427. data/spec/ffi/struct_by_ref_spec.rb +43 -0
  428. data/spec/ffi/struct_callback_spec.rb +69 -0
  429. data/spec/ffi/struct_initialize_spec.rb +35 -0
  430. data/spec/ffi/struct_packed_spec.rb +51 -0
  431. data/spec/ffi/struct_spec.rb +748 -0
  432. data/spec/ffi/typedef_spec.rb +78 -0
  433. data/spec/ffi/union_spec.rb +65 -0
  434. data/spec/ffi/variadic_spec.rb +92 -0
  435. data/spec/spec.opts +4 -0
  436. metadata +562 -0
@@ -0,0 +1,108 @@
1
+ #
2
+ # This file is part of ruby-ffi.
3
+ # For licensing, see LICENSE.SPECS
4
+ #
5
+
6
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
7
+ describe "String tests" do
8
+ include FFI
9
+ module StrLibTest
10
+ extend FFI::Library
11
+ ffi_lib TestLibrary::PATH
12
+ attach_function :ptr_ret_pointer, [ :pointer, :int], :string
13
+ attach_function :string_equals, [ :string, :string ], :int
14
+ attach_function :string_dummy, [ :string ], :void
15
+ attach_function :string_null, [ ], :string
16
+ end
17
+ it "MemoryPointer#get_string returns a tainted string" do
18
+ mp = FFI::MemoryPointer.new 1024
19
+ mp.put_string(0, "test\0")
20
+ str = mp.get_string(0)
21
+ str.tainted?.should == true
22
+ end
23
+ it "String returned by a method is tainted" do
24
+ mp = FFI::MemoryPointer.new :pointer
25
+ sp = FFI::MemoryPointer.new 1024
26
+ sp.put_string(0, "test")
27
+ mp.put_pointer(0, sp)
28
+ str = StrLibTest.ptr_ret_pointer(mp, 0)
29
+ str.should == "test"
30
+ str.tainted?.should == true
31
+ end
32
+ it "Poison null byte raises error" do
33
+ s = "123\0abc"
34
+ lambda { StrLibTest.string_equals(s, s) }.should raise_error
35
+ end
36
+ it "Tainted String parameter should throw a SecurityError" do
37
+ $SAFE = 1
38
+ str = "test"
39
+ str.taint
40
+ begin
41
+ LibTest.string_equals(str, str).should == false
42
+ rescue SecurityError
43
+ end
44
+ end if false
45
+ it "casts nil as NULL pointer" do
46
+ StrLibTest.string_dummy(nil)
47
+ end
48
+ it "return nil for NULL char*" do
49
+ StrLibTest.string_null.should == nil
50
+ end
51
+ it "reads an array of strings until encountering a NULL pointer" do
52
+ strings = ["foo", "bar", "baz", "testing", "ffi"]
53
+ ptrary = FFI::MemoryPointer.new(:pointer, 6)
54
+ ary = strings.inject([]) do |a, str|
55
+ f = FFI::MemoryPointer.new(1024)
56
+ f.put_string(0, str)
57
+ a << f
58
+ end
59
+ ary.insert(3, nil)
60
+ ptrary.write_array_of_pointer(ary)
61
+ ptrary.get_array_of_string(0).should == ["foo", "bar", "baz"]
62
+ end
63
+ it "reads an array of strings of the size specified, substituting nil when a pointer is NULL" do
64
+ strings = ["foo", "bar", "baz", "testing", "ffi"]
65
+ ptrary = FFI::MemoryPointer.new(:pointer, 6)
66
+ ary = strings.inject([]) do |a, str|
67
+ f = FFI::MemoryPointer.new(1024)
68
+ f.put_string(0, str)
69
+ a << f
70
+ end
71
+ ary.insert(2, nil)
72
+ ptrary.write_array_of_pointer(ary)
73
+ ptrary.get_array_of_string(0, 4).should == ["foo", "bar", nil, "baz"]
74
+ end
75
+ it "reads an array of strings, taking a memory offset parameter" do
76
+ strings = ["foo", "bar", "baz", "testing", "ffi"]
77
+ ptrary = FFI::MemoryPointer.new(:pointer, 5)
78
+ ary = strings.inject([]) do |a, str|
79
+ f = FFI::MemoryPointer.new(1024)
80
+ f.put_string(0, str)
81
+ a << f
82
+ end
83
+ ptrary.write_array_of_pointer(ary)
84
+ ptrary.get_array_of_string(2 * FFI.type_size(:pointer), 3).should == ["baz", "testing", "ffi"]
85
+ end
86
+ it "raises an IndexError when trying to read an array of strings out of bounds" do
87
+ strings = ["foo", "bar", "baz", "testing", "ffi"]
88
+ ptrary = FFI::MemoryPointer.new(:pointer, 5)
89
+ ary = strings.inject([]) do |a, str|
90
+ f = FFI::MemoryPointer.new(1024)
91
+ f.put_string(0, str)
92
+ a << f
93
+ end
94
+ ptrary.write_array_of_pointer(ary)
95
+ lambda { ptrary.get_array_of_string(0, 6) }.should raise_error
96
+ end
97
+ it "raises an IndexError when trying to read an array of strings using a negative offset" do
98
+ strings = ["foo", "bar", "baz", "testing", "ffi"]
99
+ ptrary = FFI::MemoryPointer.new(:pointer, 5)
100
+ ary = strings.inject([]) do |a, str|
101
+ f = FFI::MemoryPointer.new(1024)
102
+ f.put_string(0, str)
103
+ a << f
104
+ end
105
+ ptrary.write_array_of_pointer(ary)
106
+ lambda { ptrary.get_array_of_string(-1) }.should raise_error
107
+ end
108
+ end
@@ -0,0 +1,50 @@
1
+ #
2
+ # This file is part of ruby-ffi.
3
+ # For licensing, see LICENSE.SPECS
4
+ #
5
+
6
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
7
+
8
+ describe "functions returning :strptr" do
9
+
10
+ it "can attach function with :strptr return type" do
11
+ lambda do
12
+ Module.new do
13
+ extend FFI::Library
14
+ ffi_lib FFI::Library::LIBC
15
+ if !FFI::Platform.windows?
16
+ attach_function :strdup, [ :string ], :strptr
17
+ else
18
+ attach_function :_strdup, [ :string ], :strptr
19
+ end
20
+ end
21
+ end.should_not raise_error
22
+ end
23
+
24
+ module StrPtr
25
+ extend FFI::Library
26
+ ffi_lib FFI::Library::LIBC
27
+ attach_function :free, [ :pointer ], :void
28
+ if !FFI::Platform.windows?
29
+ attach_function :strdup, [ :string ], :strptr
30
+ else
31
+ attach_function :strdup, :_strdup, [ :string ], :strptr
32
+ end
33
+ end
34
+
35
+ it "should return [ String, Pointer ]" do
36
+ result = StrPtr.strdup("test")
37
+ result[0].is_a?(String).should be_true
38
+ result[1].is_a?(FFI::Pointer).should be_true
39
+ end
40
+
41
+ it "should return the correct value" do
42
+ result = StrPtr.strdup("test")
43
+ result[0].should == "test"
44
+ end
45
+
46
+ it "should return non-NULL pointer" do
47
+ result = StrPtr.strdup("test")
48
+ result[1].null?.should be_false
49
+ end
50
+ end
@@ -0,0 +1,43 @@
1
+ #
2
+ # This file is part of ruby-ffi.
3
+ # For licensing, see LICENSE.SPECS
4
+ #
5
+
6
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
7
+
8
+ describe FFI::Struct, ' by_ref' do
9
+ before :all do
10
+ @struct_class = struct_class = Class.new(FFI::Struct) do
11
+ layout :a, :pointer
12
+ end
13
+
14
+ @api = Module.new do
15
+ extend FFI::Library
16
+ ffi_lib TestLibrary::PATH
17
+ fn = FFI::Type::POINTER.size == FFI::Type::LONG.size ? :ret_ulong : ret_uint64_t
18
+ attach_function :struct_test, fn, [ struct_class.by_ref ], :pointer
19
+ end
20
+ end
21
+
22
+ it "should accept instances of exact struct class" do
23
+ s = @struct_class.new
24
+ @api.struct_test(s).should == s.pointer
25
+ end
26
+
27
+ it "should accept nil" do
28
+ @api.struct_test(nil).should == nil
29
+ end
30
+
31
+ it "should reject other types" do
32
+ lambda { @api.struct_test('test').should == nil }.should raise_error(TypeError)
33
+ end
34
+
35
+ it "should reject instances of other struct classes" do
36
+ other_class = Class.new(FFI::Struct) do
37
+ layout :a, :pointer
38
+ end
39
+
40
+ lambda { @api.struct_test(other_class.new) }.should raise_error(TypeError)
41
+ end
42
+ end
43
+
@@ -0,0 +1,69 @@
1
+ #
2
+ # This file is part of ruby-ffi.
3
+ # For licensing, see LICENSE.SPECS
4
+ #
5
+
6
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
7
+
8
+ describe FFI::Struct, ' with inline callback functions' do
9
+ it 'should be able to define inline callback field' do
10
+ module CallbackMember1
11
+ extend FFI::Library
12
+ ffi_lib TestLibrary::PATH
13
+ DUMMY_CB = callback :dummy_cb, [ :int ], :int
14
+ class TestStruct < FFI::Struct
15
+ layout \
16
+ :add, callback([ :int, :int ], :int),
17
+ :sub, callback([ :int, :int ], :int),
18
+ :cb_with_cb_parameter, callback([ DUMMY_CB, :int ], :int)
19
+ end
20
+ attach_function :struct_call_add_cb, [TestStruct, :int, :int], :int
21
+ attach_function :struct_call_sub_cb, [TestStruct, :int, :int], :int
22
+ end
23
+ end
24
+ it 'should take methods as callbacks' do
25
+ module CallbackMember2
26
+ extend FFI::Library
27
+ ffi_lib TestLibrary::PATH
28
+ class TestStruct < FFI::Struct
29
+ layout \
30
+ :add, callback([ :int, :int ], :int),
31
+ :sub, callback([ :int, :int ], :int)
32
+ end
33
+ attach_function :struct_call_add_cb, [TestStruct, :int, :int], :int
34
+ attach_function :struct_call_sub_cb, [TestStruct, :int, :int], :int
35
+ end
36
+ module StructCallbacks
37
+ def self.add a, b
38
+ a+b
39
+ end
40
+ end
41
+
42
+ ts = CallbackMember2::TestStruct.new
43
+ ts[:add] = StructCallbacks.method(:add)
44
+
45
+ CallbackMember2.struct_call_add_cb(ts, 1, 2).should == 3
46
+ end
47
+
48
+ it 'should return callable object from []' do
49
+ module CallbackMember3
50
+ extend FFI::Library
51
+ ffi_lib TestLibrary::PATH
52
+ class TestStruct < FFI::Struct
53
+ layout \
54
+ :add, callback([ :int, :int ], :int),
55
+ :sub, callback([ :int, :int ], :int)
56
+ end
57
+ attach_function :struct_call_add_cb, [TestStruct, :int, :int], :int
58
+ attach_function :struct_call_sub_cb, [TestStruct, :int, :int], :int
59
+ end
60
+
61
+ s = CallbackMember3::TestStruct.new
62
+ add = Proc.new { |a,b| a+b}
63
+ s[:add] = add
64
+ fn = s[:add]
65
+ fn.respond_to?(:call).should be_true
66
+ fn.call(1, 2).should == 3
67
+ end
68
+ end
69
+
@@ -0,0 +1,35 @@
1
+ #
2
+ # This file is part of ruby-ffi.
3
+ # For licensing, see LICENSE.SPECS
4
+ #
5
+
6
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
7
+
8
+ describe FFI::Struct, ' with an initialize function' do
9
+ it "should call the initialize function" do
10
+ class StructWithInitialize < FFI::Struct
11
+ layout :string, :string
12
+ attr_accessor :magic
13
+ def initialize
14
+ super
15
+ self.magic = 42
16
+ end
17
+ end
18
+ StructWithInitialize.new.magic.should == 42
19
+ end
20
+ end
21
+
22
+ describe FFI::ManagedStruct, ' with an initialize function' do
23
+ it "should call the initialize function" do
24
+ class ManagedStructWithInitialize < FFI::ManagedStruct
25
+ layout :string, :string
26
+ attr_accessor :magic
27
+ def initialize
28
+ super FFI::MemoryPointer.new(:pointer).put_int(0, 0x1234).get_pointer(0)
29
+ self.magic = 42
30
+ end
31
+ def self.release;end
32
+ end
33
+ ManagedStructWithInitialize.new.magic.should == 42
34
+ end
35
+ end
@@ -0,0 +1,51 @@
1
+ #
2
+ # This file is part of ruby-ffi.
3
+ # For licensing, see LICENSE.SPECS
4
+ #
5
+
6
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
7
+
8
+ describe FFI::Struct do
9
+ it "packed :char followed by :int should have size of 5" do
10
+ Class.new(FFI::Struct) do
11
+ packed
12
+ layout :c, :char, :i, :int
13
+ end.size.should == 5
14
+ end
15
+
16
+ it "packed :char followed by :int should have alignment of 1" do
17
+ Class.new(FFI::Struct) do
18
+ packed
19
+ layout :c, :char, :i, :int
20
+ end.alignment.should == 1
21
+ end
22
+
23
+ it "packed(2) :char followed by :int should have size of 6" do
24
+ Class.new(FFI::Struct) do
25
+ packed 2
26
+ layout :c, :char, :i, :int
27
+ end.size.should == 6
28
+ end
29
+
30
+ it "packed(2) :char followed by :int should have alignment of 2" do
31
+ Class.new(FFI::Struct) do
32
+ packed 2
33
+ layout :c, :char, :i, :int
34
+ end.alignment.should == 2
35
+ end
36
+
37
+ it "packed :short followed by int should have size of 6" do
38
+ Class.new(FFI::Struct) do
39
+ packed
40
+ layout :s, :short, :i, :int
41
+ end.size.should == 6
42
+ end
43
+
44
+ it "packed :short followed by int should have alignment of 1" do
45
+ Class.new(FFI::Struct) do
46
+ packed
47
+ layout :s, :short, :i, :int
48
+ end.alignment.should == 1
49
+ end
50
+
51
+ end
@@ -0,0 +1,748 @@
1
+ #
2
+ # This file is part of ruby-ffi.
3
+ # For licensing, see LICENSE.SPECS
4
+ #
5
+
6
+ require File.expand_path(File.join(File.dirname(__FILE__), "spec_helper"))
7
+ describe "Struct tests" do
8
+ StructTypes = {
9
+ 's8' => :char,
10
+ 's16' => :short,
11
+ 's32' => :int,
12
+ 's64' => :long_long,
13
+ 'long' => :long,
14
+ 'f32' => :float,
15
+ 'f64' => :double
16
+ }
17
+ module LibTest
18
+ extend FFI::Library
19
+ ffi_lib TestLibrary::PATH
20
+ attach_function :ptr_ret_pointer, [ :pointer, :int], :string
21
+ attach_function :ptr_ret_int32_t, [ :pointer, :int ], :int
22
+ attach_function :ptr_from_address, [ :ulong ], :pointer
23
+ attach_function :string_equals, [ :string, :string ], :int
24
+ [ 's8', 's16', 's32', 's64', 'f32', 'f64', 'long' ].each do |t|
25
+ attach_function "struct_align_#{t}", [ :pointer ], StructTypes[t]
26
+ end
27
+ end
28
+ class PointerMember < FFI::Struct
29
+ layout :pointer, :pointer
30
+ end
31
+ class StringMember < FFI::Struct
32
+ layout :string, :string
33
+ end
34
+ it "Struct#[:pointer]" do
35
+ magic = 0x12345678
36
+ mp = FFI::MemoryPointer.new :long
37
+ mp.put_long(0, magic)
38
+ smp = FFI::MemoryPointer.new :pointer
39
+ smp.put_pointer(0, mp)
40
+ s = PointerMember.new smp
41
+ s[:pointer].should == mp
42
+ end
43
+ it "Struct#[:pointer].nil? for NULL value" do
44
+ magic = 0x12345678
45
+ mp = FFI::MemoryPointer.new :long
46
+ mp.put_long(0, magic)
47
+ smp = FFI::MemoryPointer.new :pointer
48
+ smp.put_pointer(0, nil)
49
+ s = PointerMember.new smp
50
+ s[:pointer].null?.should == true
51
+ end
52
+ it "Struct#[:pointer]=" do
53
+ magic = 0x12345678
54
+ mp = FFI::MemoryPointer.new :long
55
+ mp.put_long(0, magic)
56
+ smp = FFI::MemoryPointer.new :pointer
57
+ s = PointerMember.new smp
58
+ s[:pointer] = mp
59
+ smp.get_pointer(0).should == mp
60
+ end
61
+ it "Struct#[:pointer]=struct" do
62
+ smp = FFI::MemoryPointer.new :pointer
63
+ s = PointerMember.new smp
64
+ lambda { s[:pointer] = s }.should_not raise_error
65
+ end
66
+ it "Struct#[:pointer]=nil" do
67
+ smp = FFI::MemoryPointer.new :pointer
68
+ s = PointerMember.new smp
69
+ s[:pointer] = nil
70
+ smp.get_pointer(0).null?.should == true
71
+ end
72
+ it "Struct#[:string]" do
73
+ magic = "test"
74
+ mp = FFI::MemoryPointer.new 1024
75
+ mp.put_string(0, magic)
76
+ smp = FFI::MemoryPointer.new :pointer
77
+ smp.put_pointer(0, mp)
78
+ s = StringMember.new smp
79
+ s[:string].should == magic
80
+ end
81
+ it "Struct#[:string].nil? for NULL value" do
82
+ smp = FFI::MemoryPointer.new :pointer
83
+ smp.put_pointer(0, nil)
84
+ s = StringMember.new smp
85
+ s[:string].nil?.should == true
86
+ end
87
+ it "Struct#layout works with :name, :type pairs" do
88
+ class PairLayout < FFI::Struct
89
+ layout :a, :int, :b, :long_long
90
+ end
91
+ ll_off = (FFI::TYPE_UINT64.alignment == 4 ? 4 : 8)
92
+ PairLayout.size.should == (ll_off + 8)
93
+ mp = FFI::MemoryPointer.new(PairLayout.size)
94
+ s = PairLayout.new mp
95
+ s[:a] = 0x12345678
96
+ mp.get_int(0).should == 0x12345678
97
+ s[:b] = 0xfee1deadbeef
98
+ mp.get_int64(ll_off).should == 0xfee1deadbeef
99
+ end
100
+ it "Struct#layout works with :name, :type, offset tuples" do
101
+ class PairLayout < FFI::Struct
102
+ layout :a, :int, 0, :b, :long_long, 4
103
+ end
104
+ PairLayout.size.should == (FFI::TYPE_UINT64.alignment == 4 ? 12 : 16)
105
+ mp = FFI::MemoryPointer.new(PairLayout.size)
106
+ s = PairLayout.new mp
107
+ s[:a] = 0x12345678
108
+ mp.get_int(0).should == 0x12345678
109
+ s[:b] = 0xfee1deadbeef
110
+ mp.get_int64(4).should == 0xfee1deadbeef
111
+ end
112
+ it "Struct#layout works with mixed :name,:type and :name,:type,offset" do
113
+ class MixedLayout < FFI::Struct
114
+ layout :a, :int, :b, :long_long, 4
115
+ end
116
+ MixedLayout.size.should == (FFI::TYPE_UINT64.alignment == 4 ? 12 : 16)
117
+ mp = FFI::MemoryPointer.new(MixedLayout.size)
118
+ s = MixedLayout.new mp
119
+ s[:a] = 0x12345678
120
+ mp.get_int(0).should == 0x12345678
121
+ s[:b] = 0xfee1deadbeef
122
+ mp.get_int64(4).should == 0xfee1deadbeef
123
+ end
124
+ rb_maj, rb_min = RUBY_VERSION.split('.')
125
+ if rb_maj.to_i >= 1 && rb_min.to_i >= 9 || RUBY_PLATFORM =~ /java/
126
+ it "Struct#layout withs with a hash of :name => type" do
127
+ class HashLayout < FFI::Struct
128
+ layout :a => :int, :b => :long_long
129
+ end
130
+ ll_off = (FFI::TYPE_UINT64.alignment == 4? 4 : 8)
131
+ HashLayout.size.should == (ll_off + 8)
132
+ mp = FFI::MemoryPointer.new(HashLayout.size)
133
+ s = HashLayout.new mp
134
+ s[:a] = 0x12345678
135
+ mp.get_int(0).should == 0x12345678
136
+ s[:b] = 0xfee1deadbeef
137
+ mp.get_int64(ll_off).should == 0xfee1deadbeef
138
+ end
139
+ end
140
+
141
+ it "subclass overrides initialize without calling super" do
142
+ class InitializeWithoutSuper < FFI::Struct
143
+ layout :a, :int, :b, :long_long, :d, [:double, 2]
144
+
145
+ def initialize(a, b)
146
+ self[:a] = a
147
+ self[:b] = b
148
+ self[:d][0] = 1.2
149
+ self[:d][1] = 3.4
150
+ end
151
+
152
+ end
153
+ s = InitializeWithoutSuper.new(0x1eefbeef, 0xdeadcafebabe)
154
+ s[:a].should == 0x1eefbeef
155
+ s[:b].should == 0xdeadcafebabe
156
+ end
157
+
158
+ it "Can use Struct subclass as parameter type" do
159
+ module StructParam
160
+ extend FFI::Library
161
+ ffi_lib TestLibrary::PATH
162
+ class TestStruct < FFI::Struct
163
+ layout :c, :char
164
+ end
165
+ attach_function :struct_field_s8, [ TestStruct.in ], :char
166
+ end
167
+ end
168
+ it "Can use Struct subclass as IN parameter type" do
169
+ module StructParam2
170
+ extend FFI::Library
171
+ ffi_lib TestLibrary::PATH
172
+ class TestStruct < FFI::Struct
173
+ layout :c, :char
174
+ end
175
+ attach_function :struct_field_s8, [ TestStruct.in ], :char
176
+ end
177
+ end
178
+ it "Can use Struct subclass as OUT parameter type" do
179
+ module StructParam3
180
+ extend FFI::Library
181
+ ffi_lib TestLibrary::PATH
182
+ class TestStruct < FFI::Struct
183
+ layout :c, :char
184
+ end
185
+ attach_function :struct_field_s8, [ TestStruct.out ], :char
186
+ end
187
+ end
188
+ it "can be passed directly as a :pointer parameter" do
189
+ class TestStruct < FFI::Struct
190
+ layout :i, :int
191
+ end
192
+ s = TestStruct.new
193
+ s[:i] = 0x12
194
+ LibTest.ptr_ret_int32_t(s, 0).should == 0x12
195
+ end
196
+ it ":char member aligned correctly" do
197
+ class AlignChar < FFI::Struct
198
+ layout :c, :char, :v, :char
199
+ end
200
+ s = AlignChar.new
201
+ s[:v] = 0x12
202
+ LibTest.struct_align_s8(s.pointer).should == 0x12
203
+ end
204
+ it ":short member aligned correctly" do
205
+ class AlignShort < FFI::Struct
206
+ layout :c, :char, :v, :short
207
+ end
208
+ s = AlignShort.alloc_in
209
+ s[:v] = 0x1234
210
+ LibTest.struct_align_s16(s.pointer).should == 0x1234
211
+ end
212
+ it ":int member aligned correctly" do
213
+ class AlignInt < FFI::Struct
214
+ layout :c, :char, :v, :int
215
+ end
216
+ s = AlignInt.alloc_in
217
+ s[:v] = 0x12345678
218
+ LibTest.struct_align_s32(s.pointer).should == 0x12345678
219
+ end
220
+ it ":long_long member aligned correctly" do
221
+ class AlignLongLong < FFI::Struct
222
+ layout :c, :char, :v, :long_long
223
+ end
224
+ s = AlignLongLong.alloc_in
225
+ s[:v] = 0x123456789abcdef0
226
+ LibTest.struct_align_s64(s.pointer).should == 0x123456789abcdef0
227
+ end
228
+ it ":long member aligned correctly" do
229
+ class AlignLong < FFI::Struct
230
+ layout :c, :char, :v, :long
231
+ end
232
+ s = AlignLong.alloc_in
233
+ s[:v] = 0x12345678
234
+ LibTest.struct_align_long(s.pointer).should == 0x12345678
235
+ end
236
+ it ":float member aligned correctly" do
237
+ class AlignFloat < FFI::Struct
238
+ layout :c, :char, :v, :float
239
+ end
240
+ s = AlignFloat.alloc_in
241
+ s[:v] = 1.23456
242
+ (LibTest.struct_align_f32(s.pointer) - 1.23456).abs.should < 0.00001
243
+ end
244
+ it ":double member aligned correctly" do
245
+ class AlignDouble < FFI::Struct
246
+ layout :c, :char, :v, :double
247
+ end
248
+ s = AlignDouble.alloc_in
249
+ s[:v] = 1.23456789
250
+ (LibTest.struct_align_f64(s.pointer) - 1.23456789).abs.should < 0.00000001
251
+ end
252
+ it ":ulong, :pointer struct" do
253
+ class ULPStruct < FFI::Struct
254
+ layout :ul, :ulong, :p, :pointer
255
+ end
256
+ s = ULPStruct.alloc_in
257
+ s[:ul] = 0xdeadbeef
258
+ s[:p] = LibTest.ptr_from_address(0x12345678)
259
+ s.pointer.get_ulong(0).should == 0xdeadbeef
260
+ end
261
+ def test_num_field(type, v)
262
+ klass = Class.new(FFI::Struct)
263
+ klass.layout :v, type, :dummy, :long
264
+
265
+ s = klass.new
266
+ s[:v] = v
267
+ s.pointer.send("get_#{type.to_s}", 0).should == v
268
+ s.pointer.send("put_#{type.to_s}", 0, 0)
269
+ s[:v].should == 0
270
+ end
271
+ def self.int_field_test(type, values)
272
+ values.each do |v|
273
+ it "#{type} field r/w (#{v.to_s(16)})" do
274
+ test_num_field(type, v)
275
+ end
276
+ end
277
+ end
278
+ int_field_test(:char, [ 0, 127, -128, -1 ])
279
+ int_field_test(:uchar, [ 0, 0x7f, 0x80, 0xff ])
280
+ int_field_test(:short, [ 0, 0x7fff, -0x8000, -1 ])
281
+ int_field_test(:ushort, [ 0, 0x7fff, 0x8000, 0xffff ])
282
+ int_field_test(:int, [ 0, 0x7fffffff, -0x80000000, -1 ])
283
+ int_field_test(:uint, [ 0, 0x7fffffff, 0x80000000, 0xffffffff ])
284
+ int_field_test(:long_long, [ 0, 0x7fffffffffffffff, -0x8000000000000000, -1 ])
285
+ int_field_test(:ulong_long, [ 0, 0x7fffffffffffffff, 0x8000000000000000, 0xffffffffffffffff ])
286
+ if FFI::Platform::LONG_SIZE == 32
287
+ int_field_test(:long, [ 0, 0x7fffffff, -0x80000000, -1 ])
288
+ int_field_test(:ulong, [ 0, 0x7fffffff, 0x80000000, 0xffffffff ])
289
+ else
290
+ int_field_test(:long, [ 0, 0x7fffffffffffffff, -0x8000000000000000, -1 ])
291
+ int_field_test(:ulong, [ 0, 0x7fffffffffffffff, 0x8000000000000000, 0xffffffffffffffff ])
292
+ end
293
+ it ":float field r/w" do
294
+ klass = Class.new(FFI::Struct)
295
+ klass.layout :v, :float, :dummy, :long
296
+
297
+ s = klass.new
298
+ value = 1.23456
299
+ s[:v] = value
300
+ (s.pointer.get_float(0) - value).abs.should < 0.0001
301
+ end
302
+ it ":double field r/w" do
303
+ klass = Class.new(FFI::Struct)
304
+ klass.layout :v, :double, :dummy, :long
305
+
306
+ s = klass.new
307
+ value = 1.23456
308
+ s[:v] = value
309
+ (s.pointer.get_double(0) - value).abs.should < 0.0001
310
+ end
311
+ module EnumFields
312
+ extend FFI::Library
313
+ TestEnum = enum :test_enum, [:c1, 10, :c2, 20, :c3, 30, :c4, 40]
314
+ class TestStruct < FFI::Struct
315
+ layout :a, :int, :c, :test_enum,
316
+ :d, [ TestEnum, TestEnum.symbols.length ]
317
+ end
318
+ end
319
+
320
+ it ":enum field r/w" do
321
+ s = EnumFields::TestStruct.new
322
+ s[:c] = :c3
323
+
324
+ s.pointer.get_uint(FFI::Type::INT32.size).should == 30
325
+ s[:c].should == :c3
326
+ end
327
+
328
+ it "array of :enum field" do
329
+ s = EnumFields::TestStruct.new
330
+ EnumFields::TestEnum.symbols.each_with_index do |val, i|
331
+ s[:d][i] = val
332
+ end
333
+
334
+ EnumFields::TestEnum.symbols.each_with_index do |val, i|
335
+ s.pointer.get_uint(FFI::Type::INT32.size * (2 + i)).should == EnumFields::TestEnum[val]
336
+ end
337
+
338
+ s[:d].each_with_index do |val, i|
339
+ val.should == EnumFields::TestEnum.symbols[i]
340
+ end
341
+ end
342
+
343
+ module CallbackMember
344
+ extend FFI::Library
345
+ ffi_lib TestLibrary::PATH
346
+ callback :add, [ :int, :int ], :int
347
+ callback :sub, [ :int, :int ], :int
348
+ class TestStruct < FFI::Struct
349
+ layout :add, :add,
350
+ :sub, :sub
351
+ end
352
+ attach_function :struct_call_add_cb, [TestStruct.in, :int, :int], :int
353
+ attach_function :struct_call_sub_cb, [TestStruct.in, :int, :int], :int
354
+ end
355
+ it "Can have CallbackInfo struct field" do
356
+ s = CallbackMember::TestStruct.new
357
+ add_proc = lambda { |a, b| a+b }
358
+ sub_proc = lambda { |a, b| a-b }
359
+ s[:add] = add_proc
360
+ s[:sub] = sub_proc
361
+ CallbackMember.struct_call_add_cb(s, 40, 2).should == 42
362
+ CallbackMember.struct_call_sub_cb(s, 44, 2).should == 42
363
+ end
364
+ it "Can return its members as a list" do
365
+ class TestStruct < FFI::Struct
366
+ layout :a, :int, :b, :int, :c, :int
367
+ end
368
+ TestStruct.members.should include(:a, :b, :c)
369
+ end
370
+ it "Can return its instance members and values as lists" do
371
+ class TestStruct < FFI::Struct
372
+ layout :a, :int, :b, :int, :c, :int
373
+ end
374
+ s = TestStruct.new
375
+ s.members.should include(:a, :b, :c)
376
+ s[:a] = 1
377
+ s[:b] = 2
378
+ s[:c] = 3
379
+ s.values.should include(1, 2, 3)
380
+ end
381
+ it 'should return an ordered field/offset pairs array' do
382
+ class TestStruct < FFI::Struct
383
+ layout :a, :int, :b, :int, :c, :int
384
+ end
385
+ s = TestStruct.new
386
+ s.offsets.should == [[:a, 0], [:b, 4], [:c, 8]]
387
+ TestStruct.offsets.should == [[:a, 0], [:b, 4], [:c, 8]]
388
+ end
389
+ it "Struct#offset_of returns offset of field within struct" do
390
+ class TestStruct < FFI::Struct
391
+ layout :a, :int, :b, :int, :c, :int
392
+ end
393
+ TestStruct.offset_of(:a).should == 0
394
+ TestStruct.offset_of(:b).should == 4
395
+ TestStruct.offset_of(:c).should == 8
396
+ end
397
+ end
398
+
399
+ describe FFI::Struct, ' with a nested struct field' do
400
+ module LibTest
401
+ extend FFI::Library
402
+ ffi_lib TestLibrary::PATH
403
+ class NestedStruct < FFI::Struct
404
+ layout :i, :int
405
+ end
406
+ class ContainerStruct < FFI::Struct
407
+ layout :first, :char, :ns, NestedStruct
408
+ end
409
+ attach_function :struct_align_nested_struct, [ :pointer ], :int
410
+ attach_function :struct_make_container_struct, [ :int ], :pointer
411
+ end
412
+ before do
413
+ @cs = LibTest::ContainerStruct.new
414
+ end
415
+ it 'should align correctly nested struct field' do
416
+ @cs[:ns][:i] = 123
417
+ LibTest.struct_align_nested_struct(@cs.to_ptr).should == 123
418
+ end
419
+ it 'should correctly calculate Container size (in bytes)' do
420
+ LibTest::ContainerStruct.size.should == 8
421
+ end
422
+ it 'should return a Struct object when the field is accessed' do
423
+ @cs[:ns].is_a?(FFI::Struct).should be_true
424
+ end
425
+ it 'should read a value from memory' do
426
+ @cs = LibTest::ContainerStruct.new(LibTest.struct_make_container_struct(123))
427
+ @cs[:ns][:i].should == 123
428
+ end
429
+ it 'should write a value to memory' do
430
+ @cs = LibTest::ContainerStruct.new(LibTest.struct_make_container_struct(123))
431
+ @cs[:ns][:i] = 456
432
+ LibTest.struct_align_nested_struct(@cs.to_ptr).should == 456
433
+ end
434
+
435
+ it 'should be able to assign struct instance to nested field' do
436
+ cs = LibTest::ContainerStruct.new(LibTest.struct_make_container_struct(123))
437
+ ns = LibTest::NestedStruct.new
438
+ ns[:i] = 567
439
+ cs[:ns] = ns
440
+ cs[:ns][:i].should == 567
441
+ LibTest.struct_align_nested_struct(cs.to_ptr).should == 567
442
+ end
443
+ end
444
+
445
+ describe FFI::Struct, ' with a nested array of structs' do
446
+ module InlineArrayOfStructs
447
+ extend FFI::Library
448
+ ffi_lib TestLibrary::PATH
449
+ class NestedStruct < FFI::Struct
450
+ layout :i, :int
451
+ end
452
+ class ContainerStruct < FFI::Struct
453
+ layout :first, :char, :ns, [ NestedStruct, 1 ]
454
+ end
455
+ attach_function :struct_align_nested_struct, [ :pointer ], :int
456
+ attach_function :struct_make_container_struct, [ :int ], :pointer
457
+ end
458
+
459
+ before do
460
+ @cs = InlineArrayOfStructs::ContainerStruct.new
461
+ end
462
+
463
+ it 'should align correctly nested struct field' do
464
+ @cs[:ns][0][:i] = 123
465
+ InlineArrayOfStructs.struct_align_nested_struct(@cs.to_ptr).should == 123
466
+ end
467
+
468
+ it 'should correctly calculate Container size (in bytes)' do
469
+ InlineArrayOfStructs::ContainerStruct.size.should == 8
470
+ end
471
+
472
+ it 'should return a Struct object when the field is accessed' do
473
+ @cs[:ns][0].is_a?(FFI::Struct).should be_true
474
+ end
475
+
476
+ it 'should read a value from memory' do
477
+ @cs = InlineArrayOfStructs::ContainerStruct.new(InlineArrayOfStructs.struct_make_container_struct(123))
478
+ @cs[:ns][0][:i].should == 123
479
+ end
480
+
481
+ it 'should write a value to memory' do
482
+ @cs = InlineArrayOfStructs::ContainerStruct.new(InlineArrayOfStructs.struct_make_container_struct(123))
483
+ @cs[:ns][0][:i] = 456
484
+ InlineArrayOfStructs.struct_align_nested_struct(@cs.to_ptr).should == 456
485
+ end
486
+
487
+ it 'should support Enumerable#each' do
488
+ @cs = InlineArrayOfStructs::ContainerStruct.new(InlineArrayOfStructs.struct_make_container_struct(123))
489
+ ints = []
490
+ @cs[:ns].each { |s| ints << s[:i] }
491
+ ints[0].should == 123
492
+ end
493
+ end
494
+
495
+ describe FFI::Struct, ' by value' do
496
+ module LibTest
497
+ extend FFI::Library
498
+ ffi_lib TestLibrary::PATH
499
+
500
+ class S8S32 < FFI::Struct
501
+ layout :s8, :char, :s32, :int
502
+ end
503
+
504
+ class StructString < FFI::Struct
505
+ layout :bytes, :string, :len, :int
506
+ end
507
+
508
+ attach_function :struct_return_s8s32, [ ], S8S32.by_value
509
+ attach_function :struct_s8s32_set, [ :char, :int ], S8S32.by_value
510
+ attach_function :struct_s8s32_get_s8, [ S8S32.by_value ], :char
511
+ attach_function :struct_s8s32_get_s32, [ S8S32.by_value ], :int
512
+ attach_function :struct_s8s32_s32_ret_s32, [ S8S32.by_value, :int ], :int
513
+ attach_function :struct_s8s32_s64_ret_s64, [ S8S32.by_value, :long_long ], :long_long
514
+ attach_function :struct_s8s32_ret_s8s32, [ S8S32.by_value ], S8S32.by_value
515
+ attach_function :struct_s32_ptr_s32_s8s32_ret_s32, [ :int, :pointer, :int, S8S32.by_value ], :int
516
+ attach_function :struct_varargs_ret_struct_string, [ :int, :varargs ], StructString.by_value
517
+ end
518
+
519
+ it 'return using pre-set values' do
520
+ s = LibTest.struct_return_s8s32
521
+ s[:s8].should == 0x7f
522
+ s[:s32].should == 0x12345678
523
+ end
524
+
525
+ it 'return using passed in values' do
526
+ s = LibTest.struct_s8s32_set(123, 456789)
527
+ s[:s8].should == 123
528
+ s[:s32].should == 456789
529
+ end
530
+
531
+ it 'parameter' do
532
+ s = LibTest::S8S32.new
533
+ s[:s8] = 0x12
534
+ s[:s32] = 0x34567890
535
+ LibTest.struct_s8s32_get_s8(s).should == 0x12
536
+ LibTest.struct_s8s32_get_s32(s).should == 0x34567890
537
+ end
538
+
539
+ it 'parameter with following s32' do
540
+ s = LibTest::S8S32.new
541
+ s[:s8] = 0x12
542
+ s[:s32] = 0x34567890
543
+
544
+ LibTest.struct_s8s32_s32_ret_s32(s, 0x1eefdead).should == 0x1eefdead
545
+ end
546
+
547
+ it 'parameter with following s64' do
548
+ s = LibTest::S8S32.new
549
+ s[:s8] = 0x12
550
+ s[:s32] = 0x34567890
551
+ end
552
+
553
+ it 'parameter with preceding s32,ptr,s32' do
554
+ s = LibTest::S8S32.new
555
+ s[:s8] = 0x12
556
+ s[:s32] = 0x34567890
557
+ out = LibTest::S8S32.new
558
+ LibTest.struct_s32_ptr_s32_s8s32_ret_s32(0x1000000, out, 0x1eafbeef, s).should == 0x34567890
559
+ out[:s8].should == s[:s8]
560
+ out[:s32].should == s[:s32]
561
+ end
562
+
563
+ it 'parameter with preceding s32,string,s32' do
564
+ s = LibTest::S8S32.new
565
+ s[:s8] = 0x12
566
+ s[:s32] = 0x34567890
567
+ out = 0.chr * 32
568
+ LibTest.struct_s32_ptr_s32_s8s32_ret_s32(0x1000000, out, 0x1eafbeef, s).should == 0x34567890
569
+ end
570
+
571
+ it 'parameter, returning struct by value' do
572
+ s = LibTest::S8S32.new
573
+ s[:s8] = 0x12
574
+ s[:s32] = 0x34567890
575
+
576
+ ret = LibTest.struct_s8s32_ret_s8s32(s)
577
+ ret[:s8].should == s[:s8]
578
+ ret[:s32].should == s[:s32]
579
+ end
580
+
581
+ it 'varargs returning a struct' do
582
+ string = "test"
583
+ s = LibTest.struct_varargs_ret_struct_string(4, :string, string)
584
+ s[:len].should == string.length
585
+ s[:bytes].should == string
586
+ end
587
+ end
588
+
589
+ describe FFI::Struct, ' with an array field' do
590
+ module LibTest
591
+ extend FFI::Library
592
+ ffi_lib TestLibrary::PATH
593
+ class StructWithArray < FFI::Struct
594
+ layout :first, :char, :a, [:int, 5]
595
+ end
596
+ attach_function :struct_make_struct_with_array, [:int, :int, :int, :int, :int], :pointer
597
+ attach_function :struct_field_array, [:pointer], :pointer
598
+ end
599
+ before do
600
+ @s = LibTest::StructWithArray.new
601
+ end
602
+ it 'should correctly calculate StructWithArray size (in bytes)' do
603
+ LibTest::StructWithArray.size.should == 24
604
+ end
605
+ it 'should read values from memory' do
606
+ @s = LibTest::StructWithArray.new(LibTest.struct_make_struct_with_array(0, 1, 2, 3, 4))
607
+ @s[:a].to_a.should == [0, 1, 2, 3, 4]
608
+ end
609
+ # it 'should cache array object for successive calls' do
610
+ # @s[:a].object_id.should == @s[:a].object_id
611
+ # end
612
+ it 'should return the number of elements in the array field' do
613
+ @s = LibTest::StructWithArray.new(LibTest.struct_make_struct_with_array(0, 1, 2, 3, 4))
614
+ @s[:a].size.should == 5
615
+ end
616
+ it 'should allow iteration through the array elements' do
617
+ @s = LibTest::StructWithArray.new(LibTest.struct_make_struct_with_array(0, 1, 2, 3, 4))
618
+ @s[:a].each_with_index { |elem, i| elem.should == i }
619
+ end
620
+ it 'should return the pointer to the array' do
621
+ @s = LibTest::StructWithArray.new(LibTest.struct_make_struct_with_array(0, 1, 2, 3, 4))
622
+ @s[:a].to_ptr.should == LibTest::struct_field_array(@s.to_ptr)
623
+ end
624
+ end
625
+
626
+ describe 'BuggedStruct' do
627
+ module LibTest
628
+ extend FFI::Library
629
+ ffi_lib TestLibrary::PATH
630
+ class BuggedStruct < FFI::Struct
631
+ layout :visible, :uchar,
632
+ :x, :uint,
633
+ :y, :uint,
634
+ :rx, :short,
635
+ :ry, :short,
636
+ :order, :uchar,
637
+ :size, :uchar
638
+ end
639
+ attach_function :bugged_struct_size, [], :uint
640
+ end
641
+ it 'should return its correct size' do
642
+ LibTest::BuggedStruct.size.should == LibTest.bugged_struct_size
643
+ end
644
+ it "offsets within struct should be correct" do
645
+ LibTest::BuggedStruct.offset_of(:visible).should == 0
646
+ LibTest::BuggedStruct.offset_of(:x).should == 4
647
+ LibTest::BuggedStruct.offset_of(:y).should == 8
648
+ LibTest::BuggedStruct.offset_of(:rx).should == 12
649
+ LibTest::BuggedStruct.offset_of(:ry).should == 14
650
+ LibTest::BuggedStruct.offset_of(:order).should == 16
651
+ LibTest::BuggedStruct.offset_of(:size).should == 17
652
+ end
653
+ it 'should return correct field/offset pairs' do
654
+ LibTest::BuggedStruct.offsets.sort do |a, b|
655
+ a[1] <=> b[1]
656
+ end.should == [[:visible, 0], [:x, 4], [:y, 8], [:rx, 12], [:ry, 14], [:order, 16], [:size, 17]]
657
+ end
658
+ end
659
+
660
+ describe "Struct allocation" do
661
+ it "MemoryPointer.new(Struct, 2)" do
662
+ class S < FFI::Struct
663
+ layout :i, :uint
664
+ end
665
+ p = FFI::MemoryPointer.new(S, 2)
666
+ p.total.should == 8
667
+ p.type_size.should == 4
668
+ p.put_uint(4, 0xdeadbeef)
669
+ S.new(p[1])[:i].should == 0xdeadbeef
670
+ p[1].address.should == (p[0].address + 4)
671
+ end
672
+
673
+ it "Buffer.new(Struct, 2)" do
674
+ class S < FFI::Struct
675
+ layout :i, :uint
676
+ end
677
+ p = FFI::Buffer.new(S, 2)
678
+ p.total.should == 8
679
+ p.type_size.should == 4
680
+ p.put_uint(4, 0xdeadbeef)
681
+ S.new(p[1])[:i].should == 0xdeadbeef
682
+ end
683
+
684
+ it "null? should be true when initialized with NULL pointer" do
685
+ class S < FFI::Struct
686
+ layout :i, :uint
687
+ end
688
+ S.new(FFI::Pointer::NULL).null?.should be_true
689
+ end
690
+
691
+ it "null? should be false when initialized with non-NULL pointer" do
692
+ class S < FFI::Struct
693
+ layout :i, :uint
694
+ end
695
+ S.new(FFI::MemoryPointer.new(S)).null?.should be_false
696
+ end
697
+
698
+ it "supports :bool as a struct member" do
699
+ lambda do
700
+ c = Class.new(FFI::Struct) do
701
+ layout :b, :bool
702
+ end
703
+ struct = c.new
704
+ struct[:b] = ! struct[:b]
705
+ end.should_not raise_error
706
+ end
707
+
708
+ end
709
+
710
+ describe "variable-length arrays" do
711
+ it "zero length array should be accepted as last field" do
712
+ lambda {
713
+ Class.new(FFI::Struct) do
714
+ layout :count, :int, :data, [ :char, 0 ]
715
+ end
716
+ }.should_not raise_error
717
+ end
718
+
719
+ it "zero length array before last element should raise error" do
720
+ lambda {
721
+ Class.new(FFI::Struct) do
722
+ layout :data, [ :char, 0 ], :count, :int
723
+ end
724
+ }.should raise_error
725
+ end
726
+
727
+ it "can access elements of array" do
728
+ struct_class = Class.new(FFI::Struct) do
729
+ layout :count, :int, :data, [ :long, 0 ]
730
+ end
731
+ s = struct_class.new(FFI::MemoryPointer.new(1024))
732
+ s[:data][0] = 0x1eadbeef
733
+ s[:data][1] = 0x12345678
734
+ s[:data][0].should == 0x1eadbeef
735
+ s[:data][1].should == 0x12345678
736
+ end
737
+
738
+ it "non-variable length array is bounds checked" do
739
+ struct_class = Class.new(FFI::Struct) do
740
+ layout :count, :int, :data, [ :long, 1 ]
741
+ end
742
+ s = struct_class.new(FFI::MemoryPointer.new(1024))
743
+ s[:data][0] = 0x1eadbeef
744
+ lambda { s[:data][1] = 0x12345678 }.should raise_error
745
+ s[:data][0].should == 0x1eadbeef
746
+ lambda { s[:data][1].should == 0x12345678 }.should raise_error
747
+ end
748
+ end