ffi 0.4.0-x86-mswin32

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 (316) hide show
  1. data/LICENSE +51 -0
  2. data/README.rdoc +69 -0
  3. data/Rakefile +142 -0
  4. data/ext/ffi_c/AbstractMemory.c +412 -0
  5. data/ext/ffi_c/AbstractMemory.h +68 -0
  6. data/ext/ffi_c/AutoPointer.c +60 -0
  7. data/ext/ffi_c/AutoPointer.h +18 -0
  8. data/ext/ffi_c/Buffer.c +171 -0
  9. data/ext/ffi_c/Callback.c +374 -0
  10. data/ext/ffi_c/Callback.h +47 -0
  11. data/ext/ffi_c/DynamicLibrary.c +213 -0
  12. data/ext/ffi_c/DynamicLibrary.h +22 -0
  13. data/ext/ffi_c/Invoker.c +962 -0
  14. data/ext/ffi_c/LastError.c +135 -0
  15. data/ext/ffi_c/LastError.h +18 -0
  16. data/ext/ffi_c/MemoryPointer.c +156 -0
  17. data/ext/ffi_c/MemoryPointer.h +20 -0
  18. data/ext/ffi_c/NullPointer.c +143 -0
  19. data/ext/ffi_c/Platform.c +59 -0
  20. data/ext/ffi_c/Platform.h +16 -0
  21. data/ext/ffi_c/Pointer.c +164 -0
  22. data/ext/ffi_c/Pointer.h +25 -0
  23. data/ext/ffi_c/Struct.c +477 -0
  24. data/ext/ffi_c/Struct.h +26 -0
  25. data/ext/ffi_c/Type.c +230 -0
  26. data/ext/ffi_c/Type.h +28 -0
  27. data/ext/ffi_c/Types.c +118 -0
  28. data/ext/ffi_c/Types.h +54 -0
  29. data/ext/ffi_c/compat.h +22 -0
  30. data/ext/ffi_c/endian.h +40 -0
  31. data/ext/ffi_c/extconf.rb +31 -0
  32. data/ext/ffi_c/ffi.c +76 -0
  33. data/ext/ffi_c/libffi.bsd.mk +34 -0
  34. data/ext/ffi_c/libffi.darwin.mk +75 -0
  35. data/ext/ffi_c/libffi.gnu.mk +29 -0
  36. data/ext/ffi_c/libffi.mk +13 -0
  37. data/ext/ffi_c/libffi/ChangeLog +3243 -0
  38. data/ext/ffi_c/libffi/ChangeLog.libffi +347 -0
  39. data/ext/ffi_c/libffi/ChangeLog.libgcj +40 -0
  40. data/ext/ffi_c/libffi/ChangeLog.v1 +764 -0
  41. data/ext/ffi_c/libffi/LICENSE +21 -0
  42. data/ext/ffi_c/libffi/Makefile.am +177 -0
  43. data/ext/ffi_c/libffi/Makefile.in +1640 -0
  44. data/ext/ffi_c/libffi/README +328 -0
  45. data/ext/ffi_c/libffi/TODO +1 -0
  46. data/ext/ffi_c/libffi/acinclude.m4 +92 -0
  47. data/ext/ffi_c/libffi/aclocal.m4 +7516 -0
  48. data/ext/ffi_c/libffi/compile +142 -0
  49. data/ext/ffi_c/libffi/config.guess +1516 -0
  50. data/ext/ffi_c/libffi/config.sub +1626 -0
  51. data/ext/ffi_c/libffi/configure +24414 -0
  52. data/ext/ffi_c/libffi/configure.ac +365 -0
  53. data/ext/ffi_c/libffi/configure.host +11 -0
  54. data/ext/ffi_c/libffi/depcomp +584 -0
  55. data/ext/ffi_c/libffi/doc/libffi.info +533 -0
  56. data/ext/ffi_c/libffi/doc/libffi.texi +541 -0
  57. data/ext/ffi_c/libffi/doc/stamp-vti +4 -0
  58. data/ext/ffi_c/libffi/doc/version.texi +4 -0
  59. data/ext/ffi_c/libffi/fficonfig.h.in +160 -0
  60. data/ext/ffi_c/libffi/include/Makefile.am +9 -0
  61. data/ext/ffi_c/libffi/include/Makefile.in +422 -0
  62. data/ext/ffi_c/libffi/include/ffi.h.in +393 -0
  63. data/ext/ffi_c/libffi/include/ffi_common.h +98 -0
  64. data/ext/ffi_c/libffi/install-sh +323 -0
  65. data/ext/ffi_c/libffi/libffi.pc.in +10 -0
  66. data/ext/ffi_c/libffi/libtool-version +29 -0
  67. data/ext/ffi_c/libffi/ltcf-c.sh +861 -0
  68. data/ext/ffi_c/libffi/ltcf-cxx.sh +1069 -0
  69. data/ext/ffi_c/libffi/ltcf-gcj.sh +700 -0
  70. data/ext/ffi_c/libffi/ltconfig +2862 -0
  71. data/ext/ffi_c/libffi/ltmain.sh +6930 -0
  72. data/ext/ffi_c/libffi/man/Makefile.am +8 -0
  73. data/ext/ffi_c/libffi/man/Makefile.in +395 -0
  74. data/ext/ffi_c/libffi/man/ffi.3 +31 -0
  75. data/ext/ffi_c/libffi/man/ffi_call.3 +103 -0
  76. data/ext/ffi_c/libffi/man/ffi_prep_cif.3 +66 -0
  77. data/ext/ffi_c/libffi/mdate-sh +201 -0
  78. data/ext/ffi_c/libffi/missing +353 -0
  79. data/ext/ffi_c/libffi/mkinstalldirs +158 -0
  80. data/ext/ffi_c/libffi/src/alpha/ffi.c +284 -0
  81. data/ext/ffi_c/libffi/src/alpha/ffitarget.h +48 -0
  82. data/ext/ffi_c/libffi/src/alpha/osf.S +366 -0
  83. data/ext/ffi_c/libffi/src/arm/ffi.c +309 -0
  84. data/ext/ffi_c/libffi/src/arm/ffitarget.h +49 -0
  85. data/ext/ffi_c/libffi/src/arm/sysv.S +299 -0
  86. data/ext/ffi_c/libffi/src/closures.c +596 -0
  87. data/ext/ffi_c/libffi/src/cris/ffi.c +383 -0
  88. data/ext/ffi_c/libffi/src/cris/ffitarget.h +51 -0
  89. data/ext/ffi_c/libffi/src/cris/sysv.S +215 -0
  90. data/ext/ffi_c/libffi/src/debug.c +59 -0
  91. data/ext/ffi_c/libffi/src/dlmalloc.c +5099 -0
  92. data/ext/ffi_c/libffi/src/frv/eabi.S +128 -0
  93. data/ext/ffi_c/libffi/src/frv/ffi.c +292 -0
  94. data/ext/ffi_c/libffi/src/frv/ffitarget.h +61 -0
  95. data/ext/ffi_c/libffi/src/ia64/ffi.c +580 -0
  96. data/ext/ffi_c/libffi/src/ia64/ffitarget.h +50 -0
  97. data/ext/ffi_c/libffi/src/ia64/ia64_flags.h +40 -0
  98. data/ext/ffi_c/libffi/src/ia64/unix.S +560 -0
  99. data/ext/ffi_c/libffi/src/java_raw_api.c +359 -0
  100. data/ext/ffi_c/libffi/src/m32r/ffi.c +232 -0
  101. data/ext/ffi_c/libffi/src/m32r/ffitarget.h +48 -0
  102. data/ext/ffi_c/libffi/src/m32r/sysv.S +121 -0
  103. data/ext/ffi_c/libffi/src/m68k/ffi.c +278 -0
  104. data/ext/ffi_c/libffi/src/m68k/ffitarget.h +49 -0
  105. data/ext/ffi_c/libffi/src/m68k/sysv.S +234 -0
  106. data/ext/ffi_c/libffi/src/mips/ffi.c +926 -0
  107. data/ext/ffi_c/libffi/src/mips/ffitarget.h +202 -0
  108. data/ext/ffi_c/libffi/src/mips/n32.S +534 -0
  109. data/ext/ffi_c/libffi/src/mips/o32.S +381 -0
  110. data/ext/ffi_c/libffi/src/pa/ffi.c +709 -0
  111. data/ext/ffi_c/libffi/src/pa/ffitarget.h +77 -0
  112. data/ext/ffi_c/libffi/src/pa/hpux32.S +368 -0
  113. data/ext/ffi_c/libffi/src/pa/linux.S +357 -0
  114. data/ext/ffi_c/libffi/src/powerpc/aix.S +225 -0
  115. data/ext/ffi_c/libffi/src/powerpc/aix_closure.S +247 -0
  116. data/ext/ffi_c/libffi/src/powerpc/asm.h +125 -0
  117. data/ext/ffi_c/libffi/src/powerpc/darwin.S +245 -0
  118. data/ext/ffi_c/libffi/src/powerpc/darwin_closure.S +317 -0
  119. data/ext/ffi_c/libffi/src/powerpc/ffi.c +1429 -0
  120. data/ext/ffi_c/libffi/src/powerpc/ffi_darwin.c +800 -0
  121. data/ext/ffi_c/libffi/src/powerpc/ffitarget.h +118 -0
  122. data/ext/ffi_c/libffi/src/powerpc/linux64.S +187 -0
  123. data/ext/ffi_c/libffi/src/powerpc/linux64_closure.S +236 -0
  124. data/ext/ffi_c/libffi/src/powerpc/ppc_closure.S +327 -0
  125. data/ext/ffi_c/libffi/src/powerpc/sysv.S +230 -0
  126. data/ext/ffi_c/libffi/src/prep_cif.c +174 -0
  127. data/ext/ffi_c/libffi/src/raw_api.c +254 -0
  128. data/ext/ffi_c/libffi/src/s390/ffi.c +780 -0
  129. data/ext/ffi_c/libffi/src/s390/ffitarget.h +60 -0
  130. data/ext/ffi_c/libffi/src/s390/sysv.S +434 -0
  131. data/ext/ffi_c/libffi/src/sh/ffi.c +716 -0
  132. data/ext/ffi_c/libffi/src/sh/ffitarget.h +49 -0
  133. data/ext/ffi_c/libffi/src/sh/sysv.S +850 -0
  134. data/ext/ffi_c/libffi/src/sh64/ffi.c +453 -0
  135. data/ext/ffi_c/libffi/src/sh64/ffitarget.h +53 -0
  136. data/ext/ffi_c/libffi/src/sh64/sysv.S +530 -0
  137. data/ext/ffi_c/libffi/src/sparc/ffi.c +610 -0
  138. data/ext/ffi_c/libffi/src/sparc/ffitarget.h +66 -0
  139. data/ext/ffi_c/libffi/src/sparc/v8.S +272 -0
  140. data/ext/ffi_c/libffi/src/sparc/v9.S +307 -0
  141. data/ext/ffi_c/libffi/src/types.c +77 -0
  142. data/ext/ffi_c/libffi/src/x86/darwin.S +443 -0
  143. data/ext/ffi_c/libffi/src/x86/darwin64.S +416 -0
  144. data/ext/ffi_c/libffi/src/x86/ffi.c +475 -0
  145. data/ext/ffi_c/libffi/src/x86/ffi64.c +572 -0
  146. data/ext/ffi_c/libffi/src/x86/ffitarget.h +90 -0
  147. data/ext/ffi_c/libffi/src/x86/freebsd.S +458 -0
  148. data/ext/ffi_c/libffi/src/x86/sysv.S +437 -0
  149. data/ext/ffi_c/libffi/src/x86/unix64.S +418 -0
  150. data/ext/ffi_c/libffi/src/x86/win32.S +391 -0
  151. data/ext/ffi_c/libffi/testsuite/Makefile.am +71 -0
  152. data/ext/ffi_c/libffi/testsuite/Makefile.in +447 -0
  153. data/ext/ffi_c/libffi/testsuite/config/default.exp +1 -0
  154. data/ext/ffi_c/libffi/testsuite/lib/libffi-dg.exp +289 -0
  155. data/ext/ffi_c/libffi/testsuite/lib/target-libpath.exp +263 -0
  156. data/ext/ffi_c/libffi/testsuite/lib/wrapper.exp +45 -0
  157. data/ext/ffi_c/libffi/testsuite/libffi.call/call.exp +36 -0
  158. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn0.c +97 -0
  159. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn1.c +89 -0
  160. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn2.c +89 -0
  161. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn3.c +90 -0
  162. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn4.c +97 -0
  163. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn5.c +99 -0
  164. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn6.c +98 -0
  165. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_stdcall.c +72 -0
  166. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_12byte.c +102 -0
  167. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_16byte.c +103 -0
  168. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_18byte.c +104 -0
  169. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_19byte.c +110 -0
  170. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_1_1byte.c +97 -0
  171. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_20byte.c +99 -0
  172. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_20byte1.c +101 -0
  173. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_24byte.c +121 -0
  174. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_2byte.c +98 -0
  175. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3_1byte.c +103 -0
  176. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3byte1.c +98 -0
  177. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3byte2.c +98 -0
  178. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_4_1byte.c +106 -0
  179. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_4byte.c +98 -0
  180. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_5_1_byte.c +117 -0
  181. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_5byte.c +106 -0
  182. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_64byte.c +132 -0
  183. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_6_1_byte.c +121 -0
  184. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_6byte.c +107 -0
  185. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_7_1_byte.c +125 -0
  186. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_7byte.c +105 -0
  187. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_8byte.c +96 -0
  188. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_9byte1.c +98 -0
  189. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_9byte2.c +99 -0
  190. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_double.c +101 -0
  191. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_float.c +99 -0
  192. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble.c +100 -0
  193. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_pointer.c +101 -0
  194. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint16.c +99 -0
  195. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint32.c +99 -0
  196. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint64.c +99 -0
  197. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint16.c +99 -0
  198. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint32.c +99 -0
  199. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint64.c +100 -0
  200. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_double.c +51 -0
  201. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_float.c +51 -0
  202. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_schar.c +82 -0
  203. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_sshort.c +82 -0
  204. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_sshortchar.c +94 -0
  205. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_uchar.c +99 -0
  206. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_ushort.c +82 -0
  207. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_ushortchar.c +94 -0
  208. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_schar.c +52 -0
  209. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_sint.c +50 -0
  210. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_sshort.c +50 -0
  211. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uchar.c +50 -0
  212. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uint.c +51 -0
  213. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ulonglong.c +54 -0
  214. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ushort.c +51 -0
  215. data/ext/ffi_c/libffi/testsuite/libffi.call/ffitest.h +86 -0
  216. data/ext/ffi_c/libffi/testsuite/libffi.call/float.c +59 -0
  217. data/ext/ffi_c/libffi/testsuite/libffi.call/float1.c +58 -0
  218. data/ext/ffi_c/libffi/testsuite/libffi.call/float2.c +57 -0
  219. data/ext/ffi_c/libffi/testsuite/libffi.call/float3.c +72 -0
  220. data/ext/ffi_c/libffi/testsuite/libffi.call/float4.c +62 -0
  221. data/ext/ffi_c/libffi/testsuite/libffi.call/many.c +69 -0
  222. data/ext/ffi_c/libffi/testsuite/libffi.call/many_win32.c +63 -0
  223. data/ext/ffi_c/libffi/testsuite/libffi.call/negint.c +53 -0
  224. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct.c +160 -0
  225. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct1.c +169 -0
  226. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct10.c +141 -0
  227. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct2.c +118 -0
  228. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct3.c +119 -0
  229. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct4.c +119 -0
  230. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct5.c +120 -0
  231. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct6.c +139 -0
  232. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct7.c +119 -0
  233. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct8.c +139 -0
  234. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct9.c +139 -0
  235. data/ext/ffi_c/libffi/testsuite/libffi.call/problem1.c +98 -0
  236. data/ext/ffi_c/libffi/testsuite/libffi.call/promotion.c +59 -0
  237. data/ext/ffi_c/libffi/testsuite/libffi.call/pyobjc-tc.c +114 -0
  238. data/ext/ffi_c/libffi/testsuite/libffi.call/return_dbl.c +35 -0
  239. data/ext/ffi_c/libffi/testsuite/libffi.call/return_dbl1.c +43 -0
  240. data/ext/ffi_c/libffi/testsuite/libffi.call/return_dbl2.c +42 -0
  241. data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl.c +35 -0
  242. data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl1.c +36 -0
  243. data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl2.c +49 -0
  244. data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl3.c +42 -0
  245. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ldl.c +34 -0
  246. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ll.c +41 -0
  247. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ll1.c +42 -0
  248. data/ext/ffi_c/libffi/testsuite/libffi.call/return_sc.c +36 -0
  249. data/ext/ffi_c/libffi/testsuite/libffi.call/return_sl.c +38 -0
  250. data/ext/ffi_c/libffi/testsuite/libffi.call/return_uc.c +38 -0
  251. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ul.c +38 -0
  252. data/ext/ffi_c/libffi/testsuite/libffi.call/strlen.c +44 -0
  253. data/ext/ffi_c/libffi/testsuite/libffi.call/strlen_win32.c +44 -0
  254. data/ext/ffi_c/libffi/testsuite/libffi.call/struct1.c +65 -0
  255. data/ext/ffi_c/libffi/testsuite/libffi.call/struct2.c +67 -0
  256. data/ext/ffi_c/libffi/testsuite/libffi.call/struct3.c +59 -0
  257. data/ext/ffi_c/libffi/testsuite/libffi.call/struct4.c +63 -0
  258. data/ext/ffi_c/libffi/testsuite/libffi.call/struct5.c +65 -0
  259. data/ext/ffi_c/libffi/testsuite/libffi.call/struct6.c +64 -0
  260. data/ext/ffi_c/libffi/testsuite/libffi.call/struct7.c +74 -0
  261. data/ext/ffi_c/libffi/testsuite/libffi.call/struct8.c +80 -0
  262. data/ext/ffi_c/libffi/testsuite/libffi.call/struct9.c +67 -0
  263. data/ext/ffi_c/libffi/testsuite/libffi.special/ffitestcxx.h +86 -0
  264. data/ext/ffi_c/libffi/testsuite/libffi.special/special.exp +38 -0
  265. data/ext/ffi_c/libffi/testsuite/libffi.special/unwindtest.cc +123 -0
  266. data/ext/ffi_c/libffi/testsuite/libffi.special/unwindtest_ffi_call.cc +53 -0
  267. data/ext/ffi_c/libffi/texinfo.tex +7482 -0
  268. data/ext/ffi_c/rbffi.h +23 -0
  269. data/gen/Rakefile +12 -0
  270. data/lib/1.8/ffi_c.so +0 -0
  271. data/lib/1.9/ffi_c.so +0 -0
  272. data/lib/ffi.rb +11 -0
  273. data/lib/ffi/autopointer.rb +61 -0
  274. data/lib/ffi/buffer.rb +0 -0
  275. data/lib/ffi/callback.rb +10 -0
  276. data/lib/ffi/enum.rb +78 -0
  277. data/lib/ffi/errno.rb +8 -0
  278. data/lib/ffi/ffi.rb +96 -0
  279. data/lib/ffi/io.rb +21 -0
  280. data/lib/ffi/library.rb +243 -0
  281. data/lib/ffi/managedstruct.rb +55 -0
  282. data/lib/ffi/memorypointer.rb +73 -0
  283. data/lib/ffi/platform.rb +78 -0
  284. data/lib/ffi/pointer.rb +119 -0
  285. data/lib/ffi/struct.rb +354 -0
  286. data/lib/ffi/tools/const_generator.rb +177 -0
  287. data/lib/ffi/tools/generator.rb +58 -0
  288. data/lib/ffi/tools/generator_task.rb +35 -0
  289. data/lib/ffi/tools/struct_generator.rb +194 -0
  290. data/lib/ffi/tools/types_generator.rb +123 -0
  291. data/lib/ffi/types.rb +153 -0
  292. data/lib/ffi/union.rb +17 -0
  293. data/lib/ffi/variadic.rb +30 -0
  294. data/spec/ffi/bool_spec.rb +24 -0
  295. data/spec/ffi/buffer_spec.rb +196 -0
  296. data/spec/ffi/callback_spec.rb +560 -0
  297. data/spec/ffi/enum_spec.rb +164 -0
  298. data/spec/ffi/errno_spec.rb +13 -0
  299. data/spec/ffi/library_spec.rb +144 -0
  300. data/spec/ffi/managed_struct_spec.rb +56 -0
  301. data/spec/ffi/number_spec.rb +231 -0
  302. data/spec/ffi/pointer_spec.rb +195 -0
  303. data/spec/ffi/rbx/attach_function_spec.rb +27 -0
  304. data/spec/ffi/rbx/memory_pointer_spec.rb +102 -0
  305. data/spec/ffi/rbx/spec_helper.rb +1 -0
  306. data/spec/ffi/rbx/struct_spec.rb +13 -0
  307. data/spec/ffi/spec_helper.rb +17 -0
  308. data/spec/ffi/string_spec.rb +103 -0
  309. data/spec/ffi/struct_callback_spec.rb +41 -0
  310. data/spec/ffi/struct_initialize_spec.rb +30 -0
  311. data/spec/ffi/struct_spec.rb +476 -0
  312. data/spec/ffi/typedef_spec.rb +48 -0
  313. data/spec/ffi/union_spec.rb +60 -0
  314. data/spec/ffi/variadic_spec.rb +84 -0
  315. data/spec/spec.opts +4 -0
  316. metadata +375 -0
@@ -0,0 +1,68 @@
1
+ #ifndef _ABSTRACTMEMORY_H
2
+ #define _ABSTRACTMEMORY_H
3
+
4
+ #include <sys/param.h>
5
+ #include <sys/types.h>
6
+ #include <stdint.h>
7
+
8
+ #include "compat.h"
9
+
10
+ #ifdef __cplusplus
11
+ extern "C" {
12
+ #endif
13
+
14
+ typedef struct AbstractMemory_ AbstractMemory;
15
+
16
+ typedef struct {
17
+ VALUE (*get)(AbstractMemory* ptr, long offset);
18
+ void (*put)(AbstractMemory* ptr, long offset, VALUE value);
19
+ } MemoryOp;
20
+
21
+ typedef struct {
22
+ MemoryOp* int8;
23
+ MemoryOp* uint8;
24
+ MemoryOp* int16;
25
+ MemoryOp* uint16;
26
+ MemoryOp* int32;
27
+ MemoryOp* uint32;
28
+ MemoryOp* int64;
29
+ MemoryOp* uint64;
30
+ MemoryOp* float32;
31
+ MemoryOp* float64;
32
+ MemoryOp* pointer;
33
+ MemoryOp* strptr;
34
+ } MemoryOps;
35
+
36
+ struct AbstractMemory_ {
37
+ char* address; // Use char* instead of void* to ensure adding to it works correctly
38
+ long size;
39
+ MemoryOps* ops;
40
+ };
41
+
42
+
43
+ static inline void
44
+ checkBounds(AbstractMemory* mem, long off, long len)
45
+ {
46
+ if ((off | len | (off + len) | (mem->size - (off + len))) < 0) {
47
+ rb_raise(rb_eIndexError, "Memory access offset=%ld size=%ld is out of bounds",
48
+ off, len);
49
+ }
50
+ }
51
+
52
+ #define MEMORY(obj) rbffi_AbstractMemory_Cast((obj), rbffi_AbstractMemoryClass)
53
+ #define MEMORY_PTR(obj) MEMORY((obj))->address
54
+ #define MEMORY_LEN(obj) MEMORY((obj))->size
55
+
56
+ extern void rbffi_AbstractMemory_Init(VALUE ffiModule);
57
+
58
+ extern AbstractMemory* rbffi_AbstractMemory_Cast(VALUE obj, VALUE klass);
59
+
60
+ extern VALUE rbffi_AbstractMemoryClass;
61
+ extern MemoryOps rbffi_AbstractMemoryOps;
62
+
63
+ #ifdef __cplusplus
64
+ }
65
+ #endif
66
+
67
+ #endif /* _ABSTRACTMEMORY_H */
68
+
@@ -0,0 +1,60 @@
1
+
2
+ #include <stdbool.h>
3
+ #include <stdint.h>
4
+ #include <limits.h>
5
+ #include <ruby.h>
6
+ #include "rbffi.h"
7
+ #include "AbstractMemory.h"
8
+ #include "Pointer.h"
9
+ #include "AutoPointer.h"
10
+
11
+ typedef struct AutoPointer {
12
+ AbstractMemory memory;
13
+ VALUE parent;
14
+ } AutoPointer;
15
+
16
+ static void autoptr_mark(AutoPointer* ptr);
17
+ static VALUE autoptr_allocate(VALUE klass);
18
+ static VALUE autoptr_set_parent(VALUE self, VALUE parent);
19
+
20
+ VALUE rbffi_AutoPointerClass = Qnil;
21
+
22
+ static VALUE
23
+ autoptr_allocate(VALUE klass)
24
+ {
25
+ AutoPointer* p;
26
+ VALUE obj = Data_Make_Struct(klass, AutoPointer, autoptr_mark, -1, p);
27
+ p->parent = Qnil;
28
+ p->memory.ops = &rbffi_AbstractMemoryOps;
29
+
30
+ return obj;
31
+ }
32
+
33
+ static VALUE
34
+ autoptr_set_parent(VALUE self, VALUE parent)
35
+ {
36
+ AutoPointer* p;
37
+ AbstractMemory* ptr = rbffi_AbstractMemory_Cast(parent, rbffi_PointerClass);
38
+
39
+ Data_Get_Struct(self, AutoPointer, p);
40
+ p->memory = *ptr;
41
+ p->parent = parent;
42
+
43
+ return self;
44
+ }
45
+
46
+ static void
47
+ autoptr_mark(AutoPointer* ptr)
48
+ {
49
+ rb_gc_mark(ptr->parent);
50
+ }
51
+
52
+ void
53
+ rbffi_AutoPointer_Init(VALUE moduleFFI)
54
+ {
55
+ rbffi_AutoPointerClass = rb_define_class_under(moduleFFI, "AutoPointer", rbffi_PointerClass);
56
+ rb_global_variable(&rbffi_AutoPointerClass);
57
+
58
+ rb_define_alloc_func(rbffi_AutoPointerClass, autoptr_allocate);
59
+ rb_define_protected_method(rbffi_AutoPointerClass, "parent=", autoptr_set_parent, 1);
60
+ }
@@ -0,0 +1,18 @@
1
+
2
+ #ifndef _AUTOPOINTER_H
3
+ #define _AUTOPOINTER_H
4
+
5
+ #ifdef __cplusplus
6
+ extern "C" {
7
+ #endif
8
+
9
+ extern void rbffi_AutoPointer_Init(VALUE ffiModule);
10
+ extern VALUE rbffi_AutoPointerClass;
11
+
12
+
13
+ #ifdef __cplusplus
14
+ }
15
+ #endif
16
+
17
+ #endif /* _AUTOPOINTER_H */
18
+
@@ -0,0 +1,171 @@
1
+ #include <stdbool.h>
2
+ #include <stdint.h>
3
+ #include <limits.h>
4
+ #include <ruby.h>
5
+ #include "rbffi.h"
6
+ #include "AbstractMemory.h"
7
+
8
+ typedef struct Buffer {
9
+ AbstractMemory memory;
10
+ char* storage; /* start of malloc area */
11
+ int type_size;
12
+ VALUE parent;
13
+ } Buffer;
14
+
15
+ static VALUE buffer_allocate(VALUE klass);
16
+ static VALUE buffer_initialize(int argc, VALUE* argv, VALUE self);
17
+ static void buffer_release(Buffer* ptr);
18
+ static void buffer_mark(Buffer* ptr);
19
+ static VALUE buffer_free(VALUE self);
20
+
21
+ static VALUE BufferClass = Qnil;
22
+ #define BUFFER(obj) ((Buffer *) rbffi_AbstractMemory_Cast((obj), BufferClass))
23
+
24
+ static VALUE
25
+ buffer_allocate(VALUE klass)
26
+ {
27
+ Buffer* buffer;
28
+ VALUE obj;
29
+
30
+ obj = Data_Make_Struct(klass, Buffer, NULL, buffer_release, buffer);
31
+ buffer->parent = Qnil;
32
+ buffer->memory.ops = &rbffi_AbstractMemoryOps;
33
+
34
+ return obj;
35
+ }
36
+
37
+ static void
38
+ buffer_release(Buffer* ptr)
39
+ {
40
+ if (ptr->storage != NULL) {
41
+ free(ptr->storage);
42
+ ptr->storage = NULL;
43
+ }
44
+
45
+ xfree(ptr);
46
+ }
47
+
48
+ static VALUE
49
+ buffer_initialize(int argc, VALUE* argv, VALUE self)
50
+ {
51
+ VALUE size = Qnil, count = Qnil, clear = Qnil;
52
+ Buffer* p;
53
+ int nargs;
54
+
55
+ Data_Get_Struct(self, Buffer, p);
56
+
57
+ nargs = rb_scan_args(argc, argv, "12", &size, &count, &clear);
58
+ p->type_size = rbffi_type_size(size);
59
+ p->memory.size = p->type_size * (nargs > 1 ? NUM2LONG(count) : 1);
60
+
61
+ p->storage = malloc(p->memory.size + 7);
62
+ if (p->storage == NULL) {
63
+ rb_raise(rb_eNoMemError, "Failed to allocate memory size=%lu bytes", p->memory.size);
64
+ }
65
+
66
+ /* ensure the memory is aligned on at least a 8 byte boundary */
67
+ p->memory.address = (void *) (((uintptr_t) p->storage + 0x7) & (uintptr_t) ~0x7UL);
68
+
69
+ if (nargs > 2 && (RTEST(clear) || clear == Qnil) && p->memory.size > 0) {
70
+ memset(p->memory.address, 0, p->memory.size);
71
+ }
72
+
73
+ if (rb_block_given_p()) {
74
+ return rb_ensure(rb_yield, self, buffer_free, self);
75
+ }
76
+
77
+ return self;
78
+ }
79
+
80
+ static VALUE
81
+ buffer_alloc_inout(int argc, VALUE* argv, VALUE klass)
82
+ {
83
+ return buffer_initialize(argc, argv, buffer_allocate(klass));
84
+ }
85
+
86
+ static VALUE
87
+ buffer_plus(VALUE self, VALUE offset)
88
+ {
89
+ Buffer* ptr = BUFFER(self);
90
+ Buffer* p;
91
+ VALUE retval;
92
+ long off = NUM2LONG(offset);
93
+
94
+ checkBounds(&ptr->memory, off, 1);
95
+
96
+ retval = Data_Make_Struct(BufferClass, Buffer, buffer_mark, -1, p);
97
+ p->memory.address = ptr->memory.address + off;
98
+ p->memory.size = ptr->memory.size - off;
99
+ p->memory.ops = &rbffi_AbstractMemoryOps;
100
+ p->parent = self;
101
+
102
+ return retval;
103
+ }
104
+
105
+ static VALUE
106
+ buffer_aref(VALUE self, VALUE offset)
107
+ {
108
+ Buffer* ptr;
109
+
110
+ Data_Get_Struct(self, Buffer, ptr);
111
+ return buffer_plus(self, INT2FIX(ptr->type_size * NUM2INT(offset)));
112
+ }
113
+
114
+ static VALUE
115
+ buffer_type_size(VALUE self)
116
+ {
117
+ Buffer* ptr;
118
+
119
+ Data_Get_Struct(self, Buffer, ptr);
120
+ return INT2NUM(ptr->type_size);
121
+ }
122
+
123
+ static VALUE
124
+ buffer_inspect(VALUE self)
125
+ {
126
+ char tmp[100];
127
+
128
+ snprintf(tmp, sizeof(tmp), "#<Buffer size=%ld>", BUFFER(self)->memory.size);
129
+
130
+ return rb_str_new2(tmp);
131
+ }
132
+
133
+ /* Only used to free the buffer if the yield in the initializer throws an exception */
134
+ static VALUE
135
+ buffer_free(VALUE self)
136
+ {
137
+ Buffer* ptr;
138
+
139
+ Data_Get_Struct(self, Buffer, ptr);
140
+ if (ptr->storage != NULL) {
141
+ free(ptr->storage);
142
+ ptr->storage = NULL;
143
+ }
144
+
145
+ return self;
146
+ }
147
+
148
+ static void
149
+ buffer_mark(Buffer* ptr)
150
+ {
151
+ rb_gc_mark(ptr->parent);
152
+ }
153
+
154
+ void
155
+ rbffi_Buffer_Init(VALUE moduleFFI)
156
+ {
157
+ BufferClass = rb_define_class_under(moduleFFI, "Buffer", rbffi_AbstractMemoryClass);
158
+
159
+ rb_global_variable(&BufferClass);
160
+ rb_define_alloc_func(BufferClass, buffer_allocate);
161
+
162
+ rb_define_singleton_method(BufferClass, "alloc_inout", buffer_alloc_inout, -1);
163
+ rb_define_singleton_method(BufferClass, "alloc_out", buffer_alloc_inout, -1);
164
+ rb_define_singleton_method(BufferClass, "alloc_in", buffer_alloc_inout, -1);
165
+
166
+ rb_define_method(BufferClass, "initialize", buffer_initialize, -1);
167
+ rb_define_method(BufferClass, "inspect", buffer_inspect, 0);
168
+ rb_define_method(BufferClass, "type_size", buffer_type_size, 0);
169
+ rb_define_method(BufferClass, "[]", buffer_aref, 1);
170
+ rb_define_method(BufferClass, "+", buffer_plus, 1);
171
+ }
@@ -0,0 +1,374 @@
1
+ #include <sys/param.h>
2
+ #include <sys/types.h>
3
+ #ifndef _WIN32
4
+ # include <sys/mman.h>
5
+ #endif
6
+ #include <ruby.h>
7
+ #include <ffi.h>
8
+ #include "AbstractMemory.h"
9
+ #include "Pointer.h"
10
+ #include "MemoryPointer.h"
11
+ #include "Callback.h"
12
+ #include "Types.h"
13
+ #include "Type.h"
14
+ #include "rbffi.h"
15
+ #include "compat.h"
16
+ #include "extconf.h"
17
+
18
+ static void cbinfo_mark(CallbackInfo* cbInfo);
19
+ static void cbinfo_free(CallbackInfo *);
20
+
21
+ #if defined(HAVE_LIBFFI) && !defined(HAVE_FFI_CLOSURE_ALLOC)
22
+ static void* ffi_closure_alloc(size_t size, void** code);
23
+ static void ffi_closure_free(void* ptr);
24
+ ffi_status ffi_prep_closure_loc(ffi_closure* closure, ffi_cif* cif,
25
+ void (*fun)(ffi_cif*, void*, void**, void*),
26
+ void* user_data, void* code);
27
+ #endif /* HAVE_FFI_CLOSURE_ALLOC */
28
+
29
+ static VALUE CallbackInfoClass = Qnil;
30
+ static VALUE NativeCallbackClass = Qnil;
31
+ static ID id_call = Qnil, id_cbtable = Qnil;
32
+
33
+ VALUE rbffi_CallbackInfoClass = Qnil;
34
+
35
+ static VALUE
36
+ cbinfo_allocate(VALUE klass)
37
+ {
38
+ CallbackInfo* cbInfo;
39
+ VALUE obj = Data_Make_Struct(klass, CallbackInfo, cbinfo_mark, cbinfo_free, cbInfo);
40
+
41
+ cbInfo->type.ffiType = &ffi_type_pointer;
42
+ cbInfo->type.size = ffi_type_pointer.size;
43
+ cbInfo->type.alignment = ffi_type_pointer.alignment;
44
+ cbInfo->type.nativeType = NATIVE_CALLBACK;
45
+ cbInfo->rbReturnType = Qnil;
46
+
47
+ return obj;
48
+ }
49
+
50
+ static VALUE
51
+ cbinfo_initialize(VALUE self, VALUE rbReturnType, VALUE rbParamTypes)
52
+ {
53
+ CallbackInfo *cbInfo;
54
+ int paramCount;
55
+ ffi_status status;
56
+ int i;
57
+
58
+ Check_Type(rbParamTypes, T_ARRAY);
59
+
60
+
61
+ paramCount = RARRAY_LEN(rbParamTypes);
62
+
63
+ Data_Get_Struct(self, CallbackInfo, cbInfo);
64
+ cbInfo->parameterCount = paramCount;
65
+ cbInfo->parameterTypes = xcalloc(paramCount, sizeof(*cbInfo->parameterTypes));
66
+ cbInfo->ffiParameterTypes = xcalloc(paramCount, sizeof(ffi_type *));
67
+ Data_Get_Struct(rbReturnType, Type, cbInfo->returnType);
68
+ cbInfo->rbReturnType = rbReturnType;
69
+ cbInfo->rbParameterTypes = rbParamTypes;
70
+
71
+ for (i = 0; i < paramCount; ++i) {
72
+ VALUE entry = rb_ary_entry(rbParamTypes, i);
73
+ if (!rb_obj_is_kind_of(entry, rbffi_TypeClass)) {
74
+ rb_raise(rb_eTypeError, "Invalid parameter type");
75
+ }
76
+ Data_Get_Struct(entry, Type, cbInfo->parameterTypes[i]);
77
+ cbInfo->ffiParameterTypes[i] = cbInfo->parameterTypes[i]->ffiType;
78
+ if (cbInfo->ffiParameterTypes[i] == NULL) {
79
+ rb_raise(rb_eArgError, "Unknown argument type: %#x", cbInfo->parameterTypes[i]->nativeType);
80
+ }
81
+ }
82
+
83
+ if (!rb_obj_is_kind_of(rbReturnType, rbffi_TypeClass)) {
84
+ rb_raise(rb_eTypeError, "Invalid return type");
85
+ }
86
+
87
+ cbInfo->ffiReturnType = cbInfo->returnType->ffiType;
88
+ if (cbInfo->ffiReturnType == NULL) {
89
+ rb_raise(rb_eArgError, "Unknown return type: %#x", cbInfo->returnType->nativeType);
90
+ }
91
+ #if defined(_WIN32) && defined(notyet)
92
+ cbInfo->abi = (flags & STDCALL) ? FFI_STDCALL : FFI_DEFAULT_ABI;
93
+ #else
94
+ cbInfo->abi = FFI_DEFAULT_ABI;
95
+ #endif
96
+ status = ffi_prep_cif(&cbInfo->ffi_cif, cbInfo->abi, cbInfo->parameterCount,
97
+ cbInfo->ffiReturnType, cbInfo->ffiParameterTypes);
98
+ switch (status) {
99
+ case FFI_BAD_ABI:
100
+ rb_raise(rb_eArgError, "Invalid ABI specified");
101
+ case FFI_BAD_TYPEDEF:
102
+ rb_raise(rb_eArgError, "Invalid argument type specified");
103
+ case FFI_OK:
104
+ break;
105
+ default:
106
+ rb_raise(rb_eArgError, "Unknown FFI error");
107
+ }
108
+ return self;
109
+ }
110
+
111
+ static void
112
+ cbinfo_mark(CallbackInfo* cbInfo)
113
+ {
114
+ rb_gc_mark(cbInfo->rbReturnType);
115
+ rb_gc_mark(cbInfo->rbParameterTypes);
116
+ }
117
+
118
+ static void
119
+ cbinfo_free(CallbackInfo* cbInfo)
120
+ {
121
+ if (cbInfo->parameterTypes != NULL) {
122
+ xfree(cbInfo->parameterTypes);
123
+ }
124
+ if (cbInfo->ffiParameterTypes != NULL) {
125
+ xfree(cbInfo->ffiParameterTypes);
126
+ }
127
+ xfree(cbInfo);
128
+ }
129
+
130
+ static void
131
+ native_callback_free(NativeCallback* cb)
132
+ {
133
+ if (cb->ffi_closure != NULL) {
134
+ ffi_closure_free(cb->ffi_closure);
135
+ }
136
+ xfree(cb);
137
+ }
138
+
139
+ static void
140
+ native_callback_mark(NativeCallback* cb)
141
+ {
142
+ rb_gc_mark(cb->rbCallbackInfo);
143
+ rb_gc_mark(cb->rbProc);
144
+ }
145
+
146
+ static void
147
+ native_callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data)
148
+ {
149
+ NativeCallback* cb = (NativeCallback *) user_data;
150
+ CallbackInfo *cbInfo = cb->cbInfo;
151
+ VALUE* rbParams;
152
+ VALUE rbReturnValue;
153
+ int i;
154
+
155
+ rbParams = ALLOCA_N(VALUE, cbInfo->parameterCount);
156
+ for (i = 0; i < cbInfo->parameterCount; ++i) {
157
+ VALUE param;
158
+ switch (cbInfo->parameterTypes[i]->nativeType) {
159
+ case NATIVE_INT8:
160
+ param = INT2NUM(*(int8_t *) parameters[i]);
161
+ break;
162
+ case NATIVE_UINT8:
163
+ param = UINT2NUM(*(uint8_t *) parameters[i]);
164
+ break;
165
+ case NATIVE_INT16:
166
+ param = INT2NUM(*(int16_t *) parameters[i]);
167
+ break;
168
+ case NATIVE_UINT16:
169
+ param = UINT2NUM(*(uint16_t *) parameters[i]);
170
+ break;
171
+ case NATIVE_INT32:
172
+ param = INT2NUM(*(int32_t *) parameters[i]);
173
+ break;
174
+ case NATIVE_UINT32:
175
+ param = UINT2NUM(*(uint32_t *) parameters[i]);
176
+ break;
177
+ case NATIVE_INT64:
178
+ param = LL2NUM(*(int64_t *) parameters[i]);
179
+ break;
180
+ case NATIVE_UINT64:
181
+ param = ULL2NUM(*(uint64_t *) parameters[i]);
182
+ break;
183
+ case NATIVE_FLOAT32:
184
+ param = rb_float_new(*(float *) parameters[i]);
185
+ break;
186
+ case NATIVE_FLOAT64:
187
+ param = rb_float_new(*(double *) parameters[i]);
188
+ break;
189
+ case NATIVE_STRING:
190
+ param = rb_tainted_str_new2(*(char **) parameters[i]);
191
+ break;
192
+ case NATIVE_POINTER:
193
+ param = rbffi_Pointer_NewInstance(*(void **) parameters[i]);
194
+ break;
195
+ case NATIVE_BOOL:
196
+ param = (*(void **) parameters[i]) ? Qtrue : Qfalse;
197
+ break;
198
+ case NATIVE_CALLBACK:
199
+ param = rbffi_NativeValue_ToRuby(cbInfo->parameterTypes[i],
200
+ rb_ary_entry(cbInfo->rbParameterTypes, i), parameters[i], Qnil);
201
+ break;
202
+ default:
203
+ param = Qnil;
204
+ break;
205
+ }
206
+ rbParams[i] = param;
207
+ }
208
+ rbReturnValue = rb_funcall2(cb->rbProc, id_call, cbInfo->parameterCount, rbParams);
209
+ if (rbReturnValue == Qnil || TYPE(rbReturnValue) == T_NIL) {
210
+ memset(retval, 0, cbInfo->ffiReturnType->size);
211
+ } else switch (cbInfo->returnType->nativeType) {
212
+ case NATIVE_INT8:
213
+ case NATIVE_INT16:
214
+ case NATIVE_INT32:
215
+ *((ffi_sarg *) retval) = NUM2INT(rbReturnValue);
216
+ break;
217
+ case NATIVE_UINT8:
218
+ case NATIVE_UINT16:
219
+ case NATIVE_UINT32:
220
+ *((ffi_arg *) retval) = NUM2UINT(rbReturnValue);
221
+ break;
222
+ case NATIVE_INT64:
223
+ *((int64_t *) retval) = NUM2LL(rbReturnValue);
224
+ break;
225
+ case NATIVE_UINT64:
226
+ *((uint64_t *) retval) = NUM2ULL(rbReturnValue);
227
+ break;
228
+ case NATIVE_FLOAT32:
229
+ *((float *) retval) = (float) NUM2DBL(rbReturnValue);
230
+ break;
231
+ case NATIVE_FLOAT64:
232
+ *((double *) retval) = NUM2DBL(rbReturnValue);
233
+ break;
234
+ case NATIVE_POINTER:
235
+ if (TYPE(rbReturnValue) == T_DATA && rb_obj_is_kind_of(rbReturnValue, rbffi_PointerClass)) {
236
+ *((void **) retval) = ((AbstractMemory *) DATA_PTR(rbReturnValue))->address;
237
+ } else {
238
+ // Default to returning NULL if not a value pointer object. handles nil case as well
239
+ *((void **) retval) = NULL;
240
+ }
241
+ break;
242
+ case NATIVE_BOOL:
243
+ *((ffi_sarg *) retval) = TYPE(rbReturnValue) == T_TRUE ? 1 : 0;
244
+ break;
245
+ case NATIVE_CALLBACK:
246
+ if (rb_obj_is_kind_of(rbReturnValue, rb_cProc) || rb_respond_to(rbReturnValue, id_call)) {
247
+ VALUE callback;
248
+
249
+ callback = rbffi_NativeCallback_ForProc(rbReturnValue, cbInfo->rbReturnType);
250
+
251
+ *((void **) retval) = ((NativeCallback *) DATA_PTR(callback))->code;
252
+ } else {
253
+ *((void **) retval) = NULL;
254
+ }
255
+ break;
256
+
257
+ default:
258
+ *((ffi_arg *) retval) = 0;
259
+ break;
260
+ }
261
+ }
262
+
263
+ static VALUE
264
+ native_callback_allocate(VALUE klass)
265
+ {
266
+ NativeCallback* closure;
267
+ VALUE obj;
268
+
269
+ obj = Data_Make_Struct(klass, NativeCallback, native_callback_mark, native_callback_free, closure);
270
+ closure->rbCallbackInfo = Qnil;
271
+ closure->rbProc = Qnil;
272
+
273
+ return obj;
274
+ }
275
+
276
+ VALUE
277
+ rbffi_NativeCallback_NewInstance(VALUE rbCallbackInfo, VALUE rbProc)
278
+ {
279
+ NativeCallback* closure = NULL;
280
+ CallbackInfo* cbInfo;
281
+ VALUE obj;
282
+ ffi_status status;
283
+
284
+ Data_Get_Struct(rbCallbackInfo, CallbackInfo, cbInfo);
285
+ obj = Data_Make_Struct(NativeCallbackClass, NativeCallback, native_callback_mark, native_callback_free, closure);
286
+ closure->cbInfo = cbInfo;
287
+ closure->rbProc = rbProc;
288
+ closure->rbCallbackInfo = rbCallbackInfo;
289
+
290
+ closure->ffi_closure = ffi_closure_alloc(sizeof(*closure->ffi_closure), &closure->code);
291
+ if (closure->ffi_closure == NULL) {
292
+ rb_raise(rb_eNoMemError, "Failed to allocate FFI native closure");
293
+ }
294
+
295
+ status = ffi_prep_closure_loc(closure->ffi_closure, &cbInfo->ffi_cif,
296
+ native_callback_invoke, closure, closure->code);
297
+ if (status != FFI_OK) {
298
+ rb_raise(rb_eArgError, "ffi_prep_closure_loc failed");
299
+ }
300
+
301
+ return obj;
302
+ }
303
+
304
+ VALUE
305
+ rbffi_NativeCallback_ForProc(VALUE proc, VALUE cbInfo)
306
+ {
307
+ VALUE callback;
308
+ VALUE cbTable = RTEST(rb_ivar_defined(proc, id_cbtable)) ? rb_ivar_get(proc, id_cbtable) : Qnil;
309
+ if (cbTable == Qnil) {
310
+ cbTable = rb_hash_new();
311
+ rb_ivar_set(proc, id_cbtable, cbTable);
312
+ }
313
+ callback = rb_hash_aref(cbTable, cbInfo);
314
+ if (callback != Qnil) {
315
+ return callback;
316
+ }
317
+ callback = rbffi_NativeCallback_NewInstance(cbInfo, proc);
318
+ rb_hash_aset(cbTable, cbInfo, callback);
319
+ return callback;
320
+ }
321
+ #if defined(HAVE_LIBFFI) && !defined(HAVE_FFI_CLOSURE_ALLOC)
322
+ /*
323
+ * versions of ffi_closure_alloc, ffi_closure_free and ffi_prep_closure_loc for older
324
+ * system libffi versions.
325
+ */
326
+ static void*
327
+ ffi_closure_alloc(size_t size, void** code)
328
+ {
329
+ void* closure;
330
+ closure = mmap(NULL, size, PROT_READ | PROT_WRITE,
331
+ MAP_ANON | MAP_PRIVATE, -1, 0);
332
+ if (closure == (void *) -1) {
333
+ return NULL;
334
+ }
335
+ memset(closure, 0, size);
336
+ *code = closure;
337
+ return closure;
338
+ }
339
+
340
+ static void
341
+ ffi_closure_free(void* ptr)
342
+ {
343
+ munmap(ptr, sizeof(ffi_closure));
344
+ }
345
+
346
+ ffi_status
347
+ ffi_prep_closure_loc(ffi_closure* closure, ffi_cif* cif,
348
+ void (*fun)(ffi_cif*, void*, void**, void*),
349
+ void* user_data, void* code)
350
+ {
351
+ ffi_status retval = ffi_prep_closure(closure, cif, fun, user_data);
352
+ if (retval == FFI_OK) {
353
+ mprotect(closure, sizeof(ffi_closure), PROT_READ | PROT_EXEC);
354
+ }
355
+ return retval;
356
+ }
357
+
358
+ #endif /* HAVE_FFI_CLOSURE_ALLOC */
359
+
360
+ void
361
+ rbffi_Callback_Init(VALUE moduleFFI)
362
+ {
363
+ rbffi_CallbackInfoClass = CallbackInfoClass = rb_define_class_under(moduleFFI, "CallbackInfo", rbffi_TypeClass);
364
+ rb_global_variable(&rbffi_CallbackInfoClass);
365
+
366
+ rb_define_alloc_func(CallbackInfoClass, cbinfo_allocate);
367
+ rb_define_method(CallbackInfoClass, "initialize", cbinfo_initialize, 2);
368
+
369
+ NativeCallbackClass = rb_define_class_under(moduleFFI, "NativeCallback", rb_cObject);
370
+ rb_global_variable(&NativeCallbackClass);
371
+ rb_define_alloc_func(NativeCallbackClass, native_callback_allocate);
372
+ id_call = rb_intern("call");
373
+ id_cbtable = rb_intern("@__ffi_callback_table__");
374
+ }