ffi 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (530) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.gitmodules +3 -0
  4. data/.travis.yml +43 -0
  5. data/.yardopts +5 -0
  6. data/CHANGELOG.md +98 -0
  7. data/COPYING +49 -0
  8. data/Gemfile +15 -0
  9. data/LICENSE +24 -0
  10. data/LICENSE.SPECS +22 -0
  11. data/README.md +112 -0
  12. data/Rakefile +268 -0
  13. data/appveyor.yml +22 -0
  14. data/ext/ffi_c/AbstractMemory.c +1109 -0
  15. data/ext/ffi_c/AbstractMemory.h +175 -0
  16. data/ext/ffi_c/ArrayType.c +162 -0
  17. data/ext/ffi_c/ArrayType.h +59 -0
  18. data/ext/ffi_c/Buffer.c +365 -0
  19. data/ext/ffi_c/Call.c +520 -0
  20. data/ext/ffi_c/Call.h +110 -0
  21. data/ext/ffi_c/ClosurePool.c +283 -0
  22. data/ext/ffi_c/ClosurePool.h +57 -0
  23. data/ext/ffi_c/DataConverter.c +91 -0
  24. data/ext/ffi_c/DynamicLibrary.c +339 -0
  25. data/ext/ffi_c/DynamicLibrary.h +98 -0
  26. data/ext/ffi_c/Function.c +1001 -0
  27. data/ext/ffi_c/Function.h +87 -0
  28. data/ext/ffi_c/FunctionInfo.c +271 -0
  29. data/ext/ffi_c/LastError.c +229 -0
  30. data/ext/ffi_c/LastError.h +47 -0
  31. data/ext/ffi_c/LongDouble.c +63 -0
  32. data/ext/ffi_c/LongDouble.h +51 -0
  33. data/ext/ffi_c/MappedType.c +168 -0
  34. data/ext/ffi_c/MappedType.h +59 -0
  35. data/ext/ffi_c/MemoryPointer.c +197 -0
  36. data/ext/ffi_c/MemoryPointer.h +53 -0
  37. data/ext/ffi_c/MethodHandle.c +358 -0
  38. data/ext/ffi_c/MethodHandle.h +55 -0
  39. data/ext/ffi_c/Platform.c +129 -0
  40. data/ext/ffi_c/Platform.h +45 -0
  41. data/ext/ffi_c/Pointer.c +508 -0
  42. data/ext/ffi_c/Pointer.h +63 -0
  43. data/ext/ffi_c/Struct.c +829 -0
  44. data/ext/ffi_c/Struct.h +106 -0
  45. data/ext/ffi_c/StructByReference.c +190 -0
  46. data/ext/ffi_c/StructByReference.h +50 -0
  47. data/ext/ffi_c/StructByValue.c +150 -0
  48. data/ext/ffi_c/StructByValue.h +55 -0
  49. data/ext/ffi_c/StructLayout.c +698 -0
  50. data/ext/ffi_c/Thread.c +353 -0
  51. data/ext/ffi_c/Thread.h +95 -0
  52. data/ext/ffi_c/Type.c +397 -0
  53. data/ext/ffi_c/Type.h +62 -0
  54. data/ext/ffi_c/Types.c +139 -0
  55. data/ext/ffi_c/Types.h +89 -0
  56. data/ext/ffi_c/Variadic.c +304 -0
  57. data/ext/ffi_c/compat.h +78 -0
  58. data/ext/ffi_c/extconf.rb +72 -0
  59. data/ext/ffi_c/ffi.c +98 -0
  60. data/ext/ffi_c/libffi.bsd.mk +40 -0
  61. data/ext/ffi_c/libffi.darwin.mk +105 -0
  62. data/ext/ffi_c/libffi.gnu.mk +32 -0
  63. data/ext/ffi_c/libffi.mk +18 -0
  64. data/ext/ffi_c/libffi.vc.mk +26 -0
  65. data/ext/ffi_c/libffi.vc64.mk +26 -0
  66. data/ext/ffi_c/libffi/.appveyor.yml +50 -0
  67. data/ext/ffi_c/libffi/.github/issue_template.md +10 -0
  68. data/ext/ffi_c/libffi/.gitignore +38 -0
  69. data/ext/ffi_c/libffi/.travis.yml +34 -0
  70. data/ext/ffi_c/libffi/.travis/ar-lib +270 -0
  71. data/ext/ffi_c/libffi/.travis/build.sh +34 -0
  72. data/ext/ffi_c/libffi/.travis/compile +351 -0
  73. data/ext/ffi_c/libffi/.travis/install.sh +22 -0
  74. data/ext/ffi_c/libffi/.travis/moxie-sim.exp +60 -0
  75. data/ext/ffi_c/libffi/.travis/site.exp +18 -0
  76. data/ext/ffi_c/libffi/ChangeLog.libffi +584 -0
  77. data/ext/ffi_c/libffi/ChangeLog.libffi-3.1 +6000 -0
  78. data/ext/ffi_c/libffi/ChangeLog.libgcj +40 -0
  79. data/ext/ffi_c/libffi/ChangeLog.v1 +764 -0
  80. data/ext/ffi_c/libffi/LICENSE +21 -0
  81. data/ext/ffi_c/libffi/LICENSE-BUILDTOOLS +352 -0
  82. data/ext/ffi_c/libffi/Makefile.am +166 -0
  83. data/ext/ffi_c/libffi/README.md +461 -0
  84. data/ext/ffi_c/libffi/acinclude.m4 +479 -0
  85. data/ext/ffi_c/libffi/autogen.sh +2 -0
  86. data/ext/ffi_c/libffi/config.guess +1466 -0
  87. data/ext/ffi_c/libffi/config.sub +1836 -0
  88. data/ext/ffi_c/libffi/configure.ac +390 -0
  89. data/ext/ffi_c/libffi/configure.host +289 -0
  90. data/ext/ffi_c/libffi/generate-darwin-source-and-headers.py +203 -0
  91. data/ext/ffi_c/libffi/include/Makefile.am +9 -0
  92. data/ext/ffi_c/libffi/include/ffi.h.in +511 -0
  93. data/ext/ffi_c/libffi/include/ffi_cfi.h +55 -0
  94. data/ext/ffi_c/libffi/include/ffi_common.h +149 -0
  95. data/ext/ffi_c/libffi/libffi.map.in +80 -0
  96. data/ext/ffi_c/libffi/libffi.pc.in +11 -0
  97. data/ext/ffi_c/libffi/libffi.xcodeproj/project.pbxproj +1043 -0
  98. data/ext/ffi_c/libffi/libtool-version +29 -0
  99. data/ext/ffi_c/libffi/m4/asmcfi.m4 +13 -0
  100. data/ext/ffi_c/libffi/m4/ax_append_flag.m4 +71 -0
  101. data/ext/ffi_c/libffi/m4/ax_cc_maxopt.m4 +194 -0
  102. data/ext/ffi_c/libffi/m4/ax_cflags_warn_all.m4 +122 -0
  103. data/ext/ffi_c/libffi/m4/ax_check_compile_flag.m4 +74 -0
  104. data/ext/ffi_c/libffi/m4/ax_compiler_vendor.m4 +87 -0
  105. data/ext/ffi_c/libffi/m4/ax_configure_args.m4 +70 -0
  106. data/ext/ffi_c/libffi/m4/ax_enable_builddir.m4 +302 -0
  107. data/ext/ffi_c/libffi/m4/ax_gcc_archflag.m4 +263 -0
  108. data/ext/ffi_c/libffi/m4/ax_gcc_x86_cpuid.m4 +89 -0
  109. data/ext/ffi_c/libffi/m4/ax_require_defined.m4 +37 -0
  110. data/ext/ffi_c/libffi/man/Makefile.am +8 -0
  111. data/ext/ffi_c/libffi/man/ffi.3 +41 -0
  112. data/ext/ffi_c/libffi/man/ffi_call.3 +103 -0
  113. data/ext/ffi_c/libffi/man/ffi_prep_cif.3 +68 -0
  114. data/ext/ffi_c/libffi/man/ffi_prep_cif_var.3 +73 -0
  115. data/ext/ffi_c/libffi/msvcc.sh +328 -0
  116. data/ext/ffi_c/libffi/src/aarch64/ffi.c +941 -0
  117. data/ext/ffi_c/libffi/src/aarch64/ffitarget.h +81 -0
  118. data/ext/ffi_c/libffi/src/aarch64/internal.h +67 -0
  119. data/ext/ffi_c/libffi/src/aarch64/sysv.S +438 -0
  120. data/ext/ffi_c/libffi/src/alpha/ffi.c +521 -0
  121. data/ext/ffi_c/libffi/src/alpha/ffitarget.h +57 -0
  122. data/ext/ffi_c/libffi/src/alpha/internal.h +23 -0
  123. data/ext/ffi_c/libffi/src/alpha/osf.S +282 -0
  124. data/ext/ffi_c/libffi/src/arc/arcompact.S +135 -0
  125. data/ext/ffi_c/libffi/src/arc/ffi.c +266 -0
  126. data/ext/ffi_c/libffi/src/arc/ffitarget.h +53 -0
  127. data/ext/ffi_c/libffi/src/arm/ffi.c +819 -0
  128. data/ext/ffi_c/libffi/src/arm/ffitarget.h +82 -0
  129. data/ext/ffi_c/libffi/src/arm/internal.h +7 -0
  130. data/ext/ffi_c/libffi/src/arm/sysv.S +383 -0
  131. data/ext/ffi_c/libffi/src/avr32/ffi.c +423 -0
  132. data/ext/ffi_c/libffi/src/avr32/ffitarget.h +55 -0
  133. data/ext/ffi_c/libffi/src/avr32/sysv.S +208 -0
  134. data/ext/ffi_c/libffi/src/bfin/ffi.c +196 -0
  135. data/ext/ffi_c/libffi/src/bfin/ffitarget.h +43 -0
  136. data/ext/ffi_c/libffi/src/bfin/sysv.S +179 -0
  137. data/ext/ffi_c/libffi/src/closures.c +966 -0
  138. data/ext/ffi_c/libffi/src/cris/ffi.c +386 -0
  139. data/ext/ffi_c/libffi/src/cris/ffitarget.h +56 -0
  140. data/ext/ffi_c/libffi/src/cris/sysv.S +215 -0
  141. data/ext/ffi_c/libffi/src/debug.c +64 -0
  142. data/ext/ffi_c/libffi/src/dlmalloc.c +5166 -0
  143. data/ext/ffi_c/libffi/src/frv/eabi.S +128 -0
  144. data/ext/ffi_c/libffi/src/frv/ffi.c +292 -0
  145. data/ext/ffi_c/libffi/src/frv/ffitarget.h +62 -0
  146. data/ext/ffi_c/libffi/src/ia64/ffi.c +604 -0
  147. data/ext/ffi_c/libffi/src/ia64/ffitarget.h +56 -0
  148. data/ext/ffi_c/libffi/src/ia64/ia64_flags.h +40 -0
  149. data/ext/ffi_c/libffi/src/ia64/unix.S +567 -0
  150. data/ext/ffi_c/libffi/src/java_raw_api.c +374 -0
  151. data/ext/ffi_c/libffi/src/m32r/ffi.c +232 -0
  152. data/ext/ffi_c/libffi/src/m32r/ffitarget.h +53 -0
  153. data/ext/ffi_c/libffi/src/m32r/sysv.S +121 -0
  154. data/ext/ffi_c/libffi/src/m68k/ffi.c +362 -0
  155. data/ext/ffi_c/libffi/src/m68k/ffitarget.h +54 -0
  156. data/ext/ffi_c/libffi/src/m68k/sysv.S +357 -0
  157. data/ext/ffi_c/libffi/src/m88k/ffi.c +400 -0
  158. data/ext/ffi_c/libffi/src/m88k/ffitarget.h +49 -0
  159. data/ext/ffi_c/libffi/src/m88k/obsd.S +209 -0
  160. data/ext/ffi_c/libffi/src/metag/ffi.c +330 -0
  161. data/ext/ffi_c/libffi/src/metag/ffitarget.h +53 -0
  162. data/ext/ffi_c/libffi/src/metag/sysv.S +311 -0
  163. data/ext/ffi_c/libffi/src/microblaze/ffi.c +321 -0
  164. data/ext/ffi_c/libffi/src/microblaze/ffitarget.h +53 -0
  165. data/ext/ffi_c/libffi/src/microblaze/sysv.S +302 -0
  166. data/ext/ffi_c/libffi/src/mips/ffi.c +1130 -0
  167. data/ext/ffi_c/libffi/src/mips/ffitarget.h +244 -0
  168. data/ext/ffi_c/libffi/src/mips/n32.S +663 -0
  169. data/ext/ffi_c/libffi/src/mips/o32.S +502 -0
  170. data/ext/ffi_c/libffi/src/moxie/eabi.S +101 -0
  171. data/ext/ffi_c/libffi/src/moxie/ffi.c +285 -0
  172. data/ext/ffi_c/libffi/src/moxie/ffitarget.h +52 -0
  173. data/ext/ffi_c/libffi/src/nios2/ffi.c +304 -0
  174. data/ext/ffi_c/libffi/src/nios2/ffitarget.h +52 -0
  175. data/ext/ffi_c/libffi/src/nios2/sysv.S +136 -0
  176. data/ext/ffi_c/libffi/src/or1k/ffi.c +328 -0
  177. data/ext/ffi_c/libffi/src/or1k/ffitarget.h +58 -0
  178. data/ext/ffi_c/libffi/src/or1k/sysv.S +107 -0
  179. data/ext/ffi_c/libffi/src/pa/ffi.c +719 -0
  180. data/ext/ffi_c/libffi/src/pa/ffitarget.h +85 -0
  181. data/ext/ffi_c/libffi/src/pa/hpux32.S +368 -0
  182. data/ext/ffi_c/libffi/src/pa/linux.S +357 -0
  183. data/ext/ffi_c/libffi/src/powerpc/aix.S +566 -0
  184. data/ext/ffi_c/libffi/src/powerpc/aix_closure.S +694 -0
  185. data/ext/ffi_c/libffi/src/powerpc/asm.h +125 -0
  186. data/ext/ffi_c/libffi/src/powerpc/darwin.S +378 -0
  187. data/ext/ffi_c/libffi/src/powerpc/darwin_closure.S +571 -0
  188. data/ext/ffi_c/libffi/src/powerpc/ffi.c +173 -0
  189. data/ext/ffi_c/libffi/src/powerpc/ffi_darwin.c +1440 -0
  190. data/ext/ffi_c/libffi/src/powerpc/ffi_linux64.c +974 -0
  191. data/ext/ffi_c/libffi/src/powerpc/ffi_powerpc.h +94 -0
  192. data/ext/ffi_c/libffi/src/powerpc/ffi_sysv.c +923 -0
  193. data/ext/ffi_c/libffi/src/powerpc/ffitarget.h +198 -0
  194. data/ext/ffi_c/libffi/src/powerpc/linux64.S +228 -0
  195. data/ext/ffi_c/libffi/src/powerpc/linux64_closure.S +488 -0
  196. data/ext/ffi_c/libffi/src/powerpc/ppc_closure.S +397 -0
  197. data/ext/ffi_c/libffi/src/powerpc/sysv.S +175 -0
  198. data/ext/ffi_c/libffi/src/prep_cif.c +261 -0
  199. data/ext/ffi_c/libffi/src/raw_api.c +267 -0
  200. data/ext/ffi_c/libffi/src/riscv/ffi.c +445 -0
  201. data/ext/ffi_c/libffi/src/riscv/ffitarget.h +68 -0
  202. data/ext/ffi_c/libffi/src/riscv/sysv.S +214 -0
  203. data/ext/ffi_c/libffi/src/s390/ffi.c +756 -0
  204. data/ext/ffi_c/libffi/src/s390/ffitarget.h +70 -0
  205. data/ext/ffi_c/libffi/src/s390/internal.h +11 -0
  206. data/ext/ffi_c/libffi/src/s390/sysv.S +325 -0
  207. data/ext/ffi_c/libffi/src/sh/ffi.c +717 -0
  208. data/ext/ffi_c/libffi/src/sh/ffitarget.h +54 -0
  209. data/ext/ffi_c/libffi/src/sh/sysv.S +850 -0
  210. data/ext/ffi_c/libffi/src/sh64/ffi.c +469 -0
  211. data/ext/ffi_c/libffi/src/sh64/ffitarget.h +58 -0
  212. data/ext/ffi_c/libffi/src/sh64/sysv.S +539 -0
  213. data/ext/ffi_c/libffi/src/sparc/ffi.c +468 -0
  214. data/ext/ffi_c/libffi/src/sparc/ffi64.c +608 -0
  215. data/ext/ffi_c/libffi/src/sparc/ffitarget.h +81 -0
  216. data/ext/ffi_c/libffi/src/sparc/internal.h +26 -0
  217. data/ext/ffi_c/libffi/src/sparc/v8.S +443 -0
  218. data/ext/ffi_c/libffi/src/sparc/v9.S +440 -0
  219. data/ext/ffi_c/libffi/src/tile/ffi.c +355 -0
  220. data/ext/ffi_c/libffi/src/tile/ffitarget.h +65 -0
  221. data/ext/ffi_c/libffi/src/tile/tile.S +360 -0
  222. data/ext/ffi_c/libffi/src/types.c +108 -0
  223. data/ext/ffi_c/libffi/src/vax/elfbsd.S +195 -0
  224. data/ext/ffi_c/libffi/src/vax/ffi.c +276 -0
  225. data/ext/ffi_c/libffi/src/vax/ffitarget.h +49 -0
  226. data/ext/ffi_c/libffi/src/x86/asmnames.h +30 -0
  227. data/ext/ffi_c/libffi/src/x86/ffi.c +753 -0
  228. data/ext/ffi_c/libffi/src/x86/ffi64.c +884 -0
  229. data/ext/ffi_c/libffi/src/x86/ffitarget.h +147 -0
  230. data/ext/ffi_c/libffi/src/x86/ffiw64.c +308 -0
  231. data/ext/ffi_c/libffi/src/x86/internal.h +29 -0
  232. data/ext/ffi_c/libffi/src/x86/internal64.h +22 -0
  233. data/ext/ffi_c/libffi/src/x86/sysv.S +1043 -0
  234. data/ext/ffi_c/libffi/src/x86/unix64.S +525 -0
  235. data/ext/ffi_c/libffi/src/x86/win64.S +232 -0
  236. data/ext/ffi_c/libffi/src/x86/win64_intel.S +237 -0
  237. data/ext/ffi_c/libffi/src/xtensa/ffi.c +298 -0
  238. data/ext/ffi_c/libffi/src/xtensa/ffitarget.h +53 -0
  239. data/ext/ffi_c/libffi/src/xtensa/sysv.S +258 -0
  240. data/ext/ffi_c/libffi/stamp-h.in +1 -0
  241. data/ext/ffi_c/libffi/testsuite/Makefile.am +117 -0
  242. data/ext/ffi_c/libffi/testsuite/config/default.exp +1 -0
  243. data/ext/ffi_c/libffi/testsuite/lib/libffi.exp +636 -0
  244. data/ext/ffi_c/libffi/testsuite/lib/target-libpath.exp +283 -0
  245. data/ext/ffi_c/libffi/testsuite/lib/wrapper.exp +45 -0
  246. data/ext/ffi_c/libffi/testsuite/libffi.bhaible/Makefile +28 -0
  247. data/ext/ffi_c/libffi/testsuite/libffi.bhaible/README +78 -0
  248. data/ext/ffi_c/libffi/testsuite/libffi.bhaible/alignof.h +50 -0
  249. data/ext/ffi_c/libffi/testsuite/libffi.bhaible/bhaible.exp +58 -0
  250. data/ext/ffi_c/libffi/testsuite/libffi.bhaible/test-call.c +1745 -0
  251. data/ext/ffi_c/libffi/testsuite/libffi.bhaible/test-callback.c +2885 -0
  252. data/ext/ffi_c/libffi/testsuite/libffi.bhaible/testcases.c +743 -0
  253. data/ext/ffi_c/libffi/testsuite/libffi.call/align_mixed.c +46 -0
  254. data/ext/ffi_c/libffi/testsuite/libffi.call/align_stdcall.c +46 -0
  255. data/ext/ffi_c/libffi/testsuite/libffi.call/call.exp +43 -0
  256. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn0.c +89 -0
  257. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn1.c +81 -0
  258. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn2.c +81 -0
  259. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn3.c +82 -0
  260. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn4.c +89 -0
  261. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn5.c +92 -0
  262. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn6.c +90 -0
  263. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_loc_fn0.c +95 -0
  264. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_simple.c +55 -0
  265. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_12byte.c +94 -0
  266. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_16byte.c +95 -0
  267. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_18byte.c +96 -0
  268. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_19byte.c +102 -0
  269. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_1_1byte.c +89 -0
  270. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_20byte.c +91 -0
  271. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_20byte1.c +93 -0
  272. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_24byte.c +113 -0
  273. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_2byte.c +90 -0
  274. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3_1byte.c +95 -0
  275. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3byte1.c +90 -0
  276. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3byte2.c +90 -0
  277. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3float.c +95 -0
  278. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_4_1byte.c +98 -0
  279. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_4byte.c +90 -0
  280. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_5_1_byte.c +109 -0
  281. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_5byte.c +98 -0
  282. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_64byte.c +124 -0
  283. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_6_1_byte.c +113 -0
  284. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_6byte.c +99 -0
  285. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_7_1_byte.c +117 -0
  286. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_7byte.c +97 -0
  287. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_8byte.c +88 -0
  288. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_9byte1.c +90 -0
  289. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_9byte2.c +91 -0
  290. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_double.c +93 -0
  291. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_float.c +91 -0
  292. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble.c +92 -0
  293. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble_split.c +132 -0
  294. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble_split2.c +115 -0
  295. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_pointer.c +95 -0
  296. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint16.c +91 -0
  297. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint32.c +91 -0
  298. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint64.c +92 -0
  299. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint16.c +91 -0
  300. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint32.c +91 -0
  301. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint64.c +93 -0
  302. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_dbls_struct.c +66 -0
  303. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_double.c +43 -0
  304. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_double_va.c +61 -0
  305. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_float.c +42 -0
  306. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_longdouble.c +105 -0
  307. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_longdouble_va.c +61 -0
  308. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_many_mixed_args.c +70 -0
  309. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_many_mixed_float_double.c +55 -0
  310. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_schar.c +74 -0
  311. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_sshort.c +74 -0
  312. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_sshortchar.c +86 -0
  313. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_uchar.c +91 -0
  314. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_ushort.c +74 -0
  315. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_ushortchar.c +86 -0
  316. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_pointer.c +74 -0
  317. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_pointer_stack.c +142 -0
  318. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_schar.c +44 -0
  319. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_sint.c +42 -0
  320. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_sshort.c +42 -0
  321. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_struct_va1.c +114 -0
  322. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uchar.c +42 -0
  323. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uchar_va.c +44 -0
  324. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uint.c +43 -0
  325. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uint_va.c +45 -0
  326. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ulong_va.c +45 -0
  327. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ulonglong.c +47 -0
  328. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ushort.c +43 -0
  329. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ushort_va.c +44 -0
  330. data/ext/ffi_c/libffi/testsuite/libffi.call/err_bad_abi.c +36 -0
  331. data/ext/ffi_c/libffi/testsuite/libffi.call/err_bad_typedef.c +26 -0
  332. data/ext/ffi_c/libffi/testsuite/libffi.call/ffitest.h +138 -0
  333. data/ext/ffi_c/libffi/testsuite/libffi.call/float.c +59 -0
  334. data/ext/ffi_c/libffi/testsuite/libffi.call/float1.c +60 -0
  335. data/ext/ffi_c/libffi/testsuite/libffi.call/float2.c +60 -0
  336. data/ext/ffi_c/libffi/testsuite/libffi.call/float3.c +74 -0
  337. data/ext/ffi_c/libffi/testsuite/libffi.call/float4.c +62 -0
  338. data/ext/ffi_c/libffi/testsuite/libffi.call/float_va.c +107 -0
  339. data/ext/ffi_c/libffi/testsuite/libffi.call/huge_struct.c +341 -0
  340. data/ext/ffi_c/libffi/testsuite/libffi.call/many.c +59 -0
  341. data/ext/ffi_c/libffi/testsuite/libffi.call/many2.c +57 -0
  342. data/ext/ffi_c/libffi/testsuite/libffi.call/many_double.c +70 -0
  343. data/ext/ffi_c/libffi/testsuite/libffi.call/many_mixed.c +78 -0
  344. data/ext/ffi_c/libffi/testsuite/libffi.call/negint.c +52 -0
  345. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct.c +152 -0
  346. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct1.c +161 -0
  347. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct10.c +134 -0
  348. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct11.c +121 -0
  349. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct2.c +110 -0
  350. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct3.c +111 -0
  351. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct4.c +111 -0
  352. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct5.c +112 -0
  353. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct6.c +131 -0
  354. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct7.c +111 -0
  355. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct8.c +131 -0
  356. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct9.c +131 -0
  357. data/ext/ffi_c/libffi/testsuite/libffi.call/offsets.c +46 -0
  358. data/ext/ffi_c/libffi/testsuite/libffi.call/pr1172638.c +127 -0
  359. data/ext/ffi_c/libffi/testsuite/libffi.call/problem1.c +90 -0
  360. data/ext/ffi_c/libffi/testsuite/libffi.call/promotion.c +59 -0
  361. data/ext/ffi_c/libffi/testsuite/libffi.call/pyobjc-tc.c +114 -0
  362. data/ext/ffi_c/libffi/testsuite/libffi.call/return_dbl.c +36 -0
  363. data/ext/ffi_c/libffi/testsuite/libffi.call/return_dbl1.c +43 -0
  364. data/ext/ffi_c/libffi/testsuite/libffi.call/return_dbl2.c +42 -0
  365. data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl.c +35 -0
  366. data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl1.c +36 -0
  367. data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl2.c +49 -0
  368. data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl3.c +42 -0
  369. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ldl.c +34 -0
  370. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ll.c +41 -0
  371. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ll1.c +43 -0
  372. data/ext/ffi_c/libffi/testsuite/libffi.call/return_sc.c +36 -0
  373. data/ext/ffi_c/libffi/testsuite/libffi.call/return_sl.c +38 -0
  374. data/ext/ffi_c/libffi/testsuite/libffi.call/return_uc.c +38 -0
  375. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ul.c +38 -0
  376. data/ext/ffi_c/libffi/testsuite/libffi.call/stret_large.c +145 -0
  377. data/ext/ffi_c/libffi/testsuite/libffi.call/stret_large2.c +148 -0
  378. data/ext/ffi_c/libffi/testsuite/libffi.call/stret_medium.c +124 -0
  379. data/ext/ffi_c/libffi/testsuite/libffi.call/stret_medium2.c +125 -0
  380. data/ext/ffi_c/libffi/testsuite/libffi.call/strlen.c +44 -0
  381. data/ext/ffi_c/libffi/testsuite/libffi.call/strlen2.c +49 -0
  382. data/ext/ffi_c/libffi/testsuite/libffi.call/strlen3.c +49 -0
  383. data/ext/ffi_c/libffi/testsuite/libffi.call/strlen4.c +55 -0
  384. data/ext/ffi_c/libffi/testsuite/libffi.call/struct1.c +67 -0
  385. data/ext/ffi_c/libffi/testsuite/libffi.call/struct10.c +57 -0
  386. data/ext/ffi_c/libffi/testsuite/libffi.call/struct2.c +67 -0
  387. data/ext/ffi_c/libffi/testsuite/libffi.call/struct3.c +60 -0
  388. data/ext/ffi_c/libffi/testsuite/libffi.call/struct4.c +64 -0
  389. data/ext/ffi_c/libffi/testsuite/libffi.call/struct5.c +66 -0
  390. data/ext/ffi_c/libffi/testsuite/libffi.call/struct6.c +64 -0
  391. data/ext/ffi_c/libffi/testsuite/libffi.call/struct7.c +74 -0
  392. data/ext/ffi_c/libffi/testsuite/libffi.call/struct8.c +81 -0
  393. data/ext/ffi_c/libffi/testsuite/libffi.call/struct9.c +68 -0
  394. data/ext/ffi_c/libffi/testsuite/libffi.call/testclosure.c +70 -0
  395. data/ext/ffi_c/libffi/testsuite/libffi.call/uninitialized.c +61 -0
  396. data/ext/ffi_c/libffi/testsuite/libffi.call/unwindtest.cc +117 -0
  397. data/ext/ffi_c/libffi/testsuite/libffi.call/unwindtest_ffi_call.cc +54 -0
  398. data/ext/ffi_c/libffi/testsuite/libffi.call/va_1.c +196 -0
  399. data/ext/ffi_c/libffi/testsuite/libffi.call/va_struct1.c +121 -0
  400. data/ext/ffi_c/libffi/testsuite/libffi.call/va_struct2.c +123 -0
  401. data/ext/ffi_c/libffi/testsuite/libffi.call/va_struct3.c +125 -0
  402. data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_align_complex.inc +91 -0
  403. data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_align_complex_double.c +10 -0
  404. data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_align_complex_float.c +10 -0
  405. data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_align_complex_longdouble.c +10 -0
  406. data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex.inc +42 -0
  407. data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex_double.c +10 -0
  408. data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex_float.c +10 -0
  409. data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex_longdouble.c +10 -0
  410. data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex_struct.inc +71 -0
  411. data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex_struct_double.c +10 -0
  412. data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex_struct_float.c +10 -0
  413. data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex_struct_longdouble.c +10 -0
  414. data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex_va.inc +80 -0
  415. data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex_va_double.c +10 -0
  416. data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex_va_float.c +16 -0
  417. data/ext/ffi_c/libffi/testsuite/libffi.complex/cls_complex_va_longdouble.c +10 -0
  418. data/ext/ffi_c/libffi/testsuite/libffi.complex/complex.exp +36 -0
  419. data/ext/ffi_c/libffi/testsuite/libffi.complex/complex.inc +51 -0
  420. data/ext/ffi_c/libffi/testsuite/libffi.complex/complex_defs_double.inc +7 -0
  421. data/ext/ffi_c/libffi/testsuite/libffi.complex/complex_defs_float.inc +7 -0
  422. data/ext/ffi_c/libffi/testsuite/libffi.complex/complex_defs_longdouble.inc +7 -0
  423. data/ext/ffi_c/libffi/testsuite/libffi.complex/complex_double.c +10 -0
  424. data/ext/ffi_c/libffi/testsuite/libffi.complex/complex_float.c +10 -0
  425. data/ext/ffi_c/libffi/testsuite/libffi.complex/complex_int.c +86 -0
  426. data/ext/ffi_c/libffi/testsuite/libffi.complex/complex_longdouble.c +10 -0
  427. data/ext/ffi_c/libffi/testsuite/libffi.complex/ffitest.h +1 -0
  428. data/ext/ffi_c/libffi/testsuite/libffi.complex/many_complex.inc +78 -0
  429. data/ext/ffi_c/libffi/testsuite/libffi.complex/many_complex_double.c +10 -0
  430. data/ext/ffi_c/libffi/testsuite/libffi.complex/many_complex_float.c +10 -0
  431. data/ext/ffi_c/libffi/testsuite/libffi.complex/many_complex_longdouble.c +10 -0
  432. data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex.inc +37 -0
  433. data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex1.inc +41 -0
  434. data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex1_double.c +10 -0
  435. data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex1_float.c +10 -0
  436. data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex1_longdouble.c +10 -0
  437. data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex2.inc +44 -0
  438. data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex2_double.c +10 -0
  439. data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex2_float.c +10 -0
  440. data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex2_longdouble.c +10 -0
  441. data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex_double.c +10 -0
  442. data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex_float.c +10 -0
  443. data/ext/ffi_c/libffi/testsuite/libffi.complex/return_complex_longdouble.c +10 -0
  444. data/ext/ffi_c/libffi/testsuite/libffi.go/aa-direct.c +34 -0
  445. data/ext/ffi_c/libffi/testsuite/libffi.go/closure1.c +28 -0
  446. data/ext/ffi_c/libffi/testsuite/libffi.go/ffitest.h +1 -0
  447. data/ext/ffi_c/libffi/testsuite/libffi.go/go.exp +36 -0
  448. data/ext/ffi_c/libffi/testsuite/libffi.go/static-chain.h +19 -0
  449. data/ext/ffi_c/rbffi.h +57 -0
  450. data/ext/ffi_c/rbffi_endian.h +59 -0
  451. data/ext/ffi_c/win32/stdbool.h +8 -0
  452. data/ext/ffi_c/win32/stdint.h +201 -0
  453. data/ffi.gemspec +36 -0
  454. data/lib/ffi.rb +20 -0
  455. data/lib/ffi/autopointer.rb +203 -0
  456. data/lib/ffi/buffer.rb +4 -0
  457. data/lib/ffi/callback.rb +4 -0
  458. data/lib/ffi/enum.rb +296 -0
  459. data/lib/ffi/errno.rb +43 -0
  460. data/lib/ffi/ffi.rb +44 -0
  461. data/lib/ffi/io.rb +62 -0
  462. data/lib/ffi/library.rb +588 -0
  463. data/lib/ffi/managedstruct.rb +84 -0
  464. data/lib/ffi/memorypointer.rb +1 -0
  465. data/lib/ffi/platform.rb +170 -0
  466. data/lib/ffi/platform/aarch64-freebsd/types.conf +128 -0
  467. data/lib/ffi/platform/aarch64-freebsd12/types.conf +128 -0
  468. data/lib/ffi/platform/aarch64-linux/types.conf +104 -0
  469. data/lib/ffi/platform/arm-freebsd/types.conf +152 -0
  470. data/lib/ffi/platform/arm-freebsd12/types.conf +152 -0
  471. data/lib/ffi/platform/arm-linux/types.conf +104 -0
  472. data/lib/ffi/platform/i386-cygwin/types.conf +3 -0
  473. data/lib/ffi/platform/i386-darwin/types.conf +100 -0
  474. data/lib/ffi/platform/i386-freebsd/types.conf +152 -0
  475. data/lib/ffi/platform/i386-freebsd12/types.conf +152 -0
  476. data/lib/ffi/platform/i386-gnu/types.conf +107 -0
  477. data/lib/ffi/platform/i386-linux/types.conf +103 -0
  478. data/lib/ffi/platform/i386-netbsd/types.conf +126 -0
  479. data/lib/ffi/platform/i386-openbsd/types.conf +128 -0
  480. data/lib/ffi/platform/i386-solaris/types.conf +122 -0
  481. data/lib/ffi/platform/i386-windows/types.conf +105 -0
  482. data/lib/ffi/platform/ia64-linux/types.conf +104 -0
  483. data/lib/ffi/platform/mips-linux/types.conf +102 -0
  484. data/lib/ffi/platform/mips64-linux/types.conf +104 -0
  485. data/lib/ffi/platform/mips64el-linux/types.conf +104 -0
  486. data/lib/ffi/platform/mipsel-linux/types.conf +102 -0
  487. data/lib/ffi/platform/mipsisa32r6-linux/types.conf +102 -0
  488. data/lib/ffi/platform/mipsisa32r6el-linux/types.conf +102 -0
  489. data/lib/ffi/platform/mipsisa64r6-linux/types.conf +104 -0
  490. data/lib/ffi/platform/mipsisa64r6el-linux/types.conf +104 -0
  491. data/lib/ffi/platform/powerpc-aix/types.conf +180 -0
  492. data/lib/ffi/platform/powerpc-darwin/types.conf +100 -0
  493. data/lib/ffi/platform/powerpc-linux/types.conf +100 -0
  494. data/lib/ffi/platform/powerpc64-linux/types.conf +104 -0
  495. data/lib/ffi/platform/s390-linux/types.conf +102 -0
  496. data/lib/ffi/platform/s390x-linux/types.conf +102 -0
  497. data/lib/ffi/platform/sparc-linux/types.conf +102 -0
  498. data/lib/ffi/platform/sparc-solaris/types.conf +128 -0
  499. data/lib/ffi/platform/sparc64-linux/types.conf +102 -0
  500. data/lib/ffi/platform/sparcv9-solaris/types.conf +128 -0
  501. data/lib/ffi/platform/x86_64-cygwin/types.conf +3 -0
  502. data/lib/ffi/platform/x86_64-darwin/types.conf +126 -0
  503. data/lib/ffi/platform/x86_64-freebsd/types.conf +128 -0
  504. data/lib/ffi/platform/x86_64-freebsd12/types.conf +128 -0
  505. data/lib/ffi/platform/x86_64-linux/types.conf +102 -0
  506. data/lib/ffi/platform/x86_64-netbsd/types.conf +128 -0
  507. data/lib/ffi/platform/x86_64-openbsd/types.conf +134 -0
  508. data/lib/ffi/platform/x86_64-solaris/types.conf +122 -0
  509. data/lib/ffi/platform/x86_64-windows/types.conf +120 -0
  510. data/lib/ffi/pointer.rb +160 -0
  511. data/lib/ffi/struct.rb +371 -0
  512. data/lib/ffi/struct_layout_builder.rb +227 -0
  513. data/lib/ffi/tools/const_generator.rb +229 -0
  514. data/lib/ffi/tools/generator.rb +60 -0
  515. data/lib/ffi/tools/generator_task.rb +36 -0
  516. data/lib/ffi/tools/struct_generator.rb +194 -0
  517. data/lib/ffi/tools/types_generator.rb +134 -0
  518. data/lib/ffi/types.rb +194 -0
  519. data/lib/ffi/union.rb +43 -0
  520. data/lib/ffi/variadic.rb +78 -0
  521. data/lib/ffi/version.rb +3 -0
  522. data/samples/getlogin.rb +8 -0
  523. data/samples/getpid.rb +8 -0
  524. data/samples/gettimeofday.rb +18 -0
  525. data/samples/hello.rb +7 -0
  526. data/samples/inotify.rb +60 -0
  527. data/samples/pty.rb +76 -0
  528. data/samples/qsort.rb +21 -0
  529. data/samples/sample_helper.rb +6 -0
  530. metadata +658 -0
@@ -0,0 +1,1001 @@
1
+ /*
2
+ * Copyright (c) 2009-2011 Wayne Meissner
3
+ *
4
+ * Copyright (c) 2008-2013, Ruby FFI project contributors
5
+ * All rights reserved.
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without
8
+ * modification, are permitted provided that the following conditions are met:
9
+ * * Redistributions of source code must retain the above copyright
10
+ * notice, this list of conditions and the following disclaimer.
11
+ * * Redistributions in binary form must reproduce the above copyright
12
+ * notice, this list of conditions and the following disclaimer in the
13
+ * documentation and/or other materials provided with the distribution.
14
+ * * Neither the name of the Ruby FFI project nor the
15
+ * names of its contributors may be used to endorse or promote products
16
+ * derived from this software without specific prior written permission.
17
+ *
18
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
22
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+ */
29
+
30
+ #ifndef _MSC_VER
31
+ #include <sys/param.h>
32
+ #endif
33
+ #include <sys/types.h>
34
+ #ifndef _WIN32
35
+ # include <sys/mman.h>
36
+ # include <unistd.h>
37
+ #endif
38
+
39
+ #include <stdio.h>
40
+ #ifndef _MSC_VER
41
+ # include <stdint.h>
42
+ # include <stdbool.h>
43
+ #else
44
+ # include "win32/stdbool.h"
45
+ # if !defined(INT8_MIN)
46
+ # include "win32/stdint.h"
47
+ # endif
48
+ #endif
49
+ #include <ruby.h>
50
+ #if defined(HAVE_RUBY_THREAD_H)
51
+ #include <ruby/thread.h>
52
+ #endif
53
+
54
+ #include <ffi.h>
55
+ #if defined(HAVE_NATIVETHREAD) && !defined(_WIN32)
56
+ #include <pthread.h>
57
+ #endif
58
+ #include <fcntl.h>
59
+
60
+ #include "rbffi.h"
61
+ #include "compat.h"
62
+
63
+ #include "AbstractMemory.h"
64
+ #include "Pointer.h"
65
+ #include "Struct.h"
66
+ #include "Platform.h"
67
+ #include "Type.h"
68
+ #include "LastError.h"
69
+ #include "Call.h"
70
+ #include "ClosurePool.h"
71
+ #include "MappedType.h"
72
+ #include "Thread.h"
73
+ #include "LongDouble.h"
74
+ #include "MethodHandle.h"
75
+ #include "Function.h"
76
+
77
+ typedef struct Function_ {
78
+ Pointer base;
79
+ FunctionType* info;
80
+ MethodHandle* methodHandle;
81
+ bool autorelease;
82
+ Closure* closure;
83
+ VALUE rbProc;
84
+ VALUE rbFunctionInfo;
85
+ } Function;
86
+
87
+ static void function_mark(Function *);
88
+ static void function_free(Function *);
89
+ static VALUE function_init(VALUE self, VALUE rbFunctionInfo, VALUE rbProc);
90
+ static void callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data);
91
+ static bool callback_prep(void* ctx, void* code, Closure* closure, char* errmsg, size_t errmsgsize);
92
+ static void* callback_with_gvl(void* data);
93
+ static VALUE invoke_callback(void* data);
94
+ static VALUE save_callback_exception(void* data, VALUE exc);
95
+
96
+ #define DEFER_ASYNC_CALLBACK 1
97
+
98
+
99
+ #if defined(DEFER_ASYNC_CALLBACK)
100
+ static VALUE async_cb_event(void *);
101
+ static VALUE async_cb_call(void *);
102
+ #endif
103
+
104
+ #ifdef HAVE_RB_THREAD_CALL_WITH_GVL
105
+ extern void *rb_thread_call_with_gvl(void *(*func)(void *), void *data1);
106
+ #endif
107
+
108
+ VALUE rbffi_FunctionClass = Qnil;
109
+
110
+ #if defined(DEFER_ASYNC_CALLBACK)
111
+ static VALUE async_cb_thread = Qnil;
112
+ #endif
113
+
114
+ static ID id_call = 0, id_to_native = 0, id_from_native = 0, id_cbtable = 0, id_cb_ref = 0;
115
+
116
+ struct gvl_callback {
117
+ Closure* closure;
118
+ void* retval;
119
+ void** parameters;
120
+ bool done;
121
+ rbffi_frame_t *frame;
122
+ #if defined(DEFER_ASYNC_CALLBACK)
123
+ struct gvl_callback* next;
124
+ # ifndef _WIN32
125
+ pthread_cond_t async_cond;
126
+ pthread_mutex_t async_mutex;
127
+ # else
128
+ HANDLE async_event;
129
+ # endif
130
+ #endif
131
+ };
132
+
133
+
134
+ #if defined(DEFER_ASYNC_CALLBACK)
135
+ static struct gvl_callback* async_cb_list = NULL;
136
+ # ifndef _WIN32
137
+ static pthread_mutex_t async_cb_mutex = PTHREAD_MUTEX_INITIALIZER;
138
+ static pthread_cond_t async_cb_cond = PTHREAD_COND_INITIALIZER;
139
+ # if !(defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL))
140
+ static int async_cb_pipe[2];
141
+ # endif
142
+ # else
143
+ static HANDLE async_cb_cond;
144
+ static CRITICAL_SECTION async_cb_lock;
145
+ # if !(defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL))
146
+ static int async_cb_pipe[2];
147
+ # endif
148
+ # endif
149
+ #endif
150
+
151
+
152
+ static VALUE
153
+ function_allocate(VALUE klass)
154
+ {
155
+ Function *fn;
156
+ VALUE obj;
157
+
158
+ obj = Data_Make_Struct(klass, Function, function_mark, function_free, fn);
159
+
160
+ fn->base.memory.flags = MEM_RD;
161
+ fn->base.rbParent = Qnil;
162
+ fn->rbProc = Qnil;
163
+ fn->rbFunctionInfo = Qnil;
164
+ fn->autorelease = true;
165
+
166
+ return obj;
167
+ }
168
+
169
+ static void
170
+ function_mark(Function *fn)
171
+ {
172
+ rb_gc_mark(fn->base.rbParent);
173
+ rb_gc_mark(fn->rbProc);
174
+ rb_gc_mark(fn->rbFunctionInfo);
175
+ }
176
+
177
+ static void
178
+ function_free(Function *fn)
179
+ {
180
+ if (fn->methodHandle != NULL) {
181
+ rbffi_MethodHandle_Free(fn->methodHandle);
182
+ }
183
+
184
+ if (fn->closure != NULL && fn->autorelease) {
185
+ rbffi_Closure_Free(fn->closure);
186
+ }
187
+
188
+ xfree(fn);
189
+ }
190
+
191
+ /*
192
+ * @param [Type, Symbol] return_type return type for the function
193
+ * @param [Array<Type, Symbol>] param_types array of parameters types
194
+ * @param [Hash] options see {FFI::FunctionType} for available options
195
+ * @return [self]
196
+ * A new Function instance.
197
+ *
198
+ * Define a function from a Proc or a block.
199
+ *
200
+ * @overload initialize(return_type, param_types, options = {}) { |i| ... }
201
+ * @yieldparam i parameters for the function
202
+ * @overload initialize(return_type, param_types, proc, options = {})
203
+ * @param [Proc] proc
204
+ */
205
+ static VALUE
206
+ function_initialize(int argc, VALUE* argv, VALUE self)
207
+ {
208
+
209
+ VALUE rbReturnType = Qnil, rbParamTypes = Qnil, rbProc = Qnil, rbOptions = Qnil;
210
+ VALUE rbFunctionInfo = Qnil;
211
+ VALUE infoArgv[3];
212
+ int nargs;
213
+
214
+ nargs = rb_scan_args(argc, argv, "22", &rbReturnType, &rbParamTypes, &rbProc, &rbOptions);
215
+
216
+ /*
217
+ * Callback with block,
218
+ * e.g. Function.new(:int, [ :int ]) { |i| blah }
219
+ * or Function.new(:int, [ :int ], { :convention => :stdcall }) { |i| blah }
220
+ */
221
+ if (rb_block_given_p()) {
222
+ if (nargs > 3) {
223
+ rb_raise(rb_eArgError, "cannot create function with both proc/address and block");
224
+ }
225
+ rbOptions = rbProc;
226
+ rbProc = rb_block_proc();
227
+ } else {
228
+ /* Callback with proc, or Function with address
229
+ * e.g. Function.new(:int, [ :int ], Proc.new { |i| })
230
+ * Function.new(:int, [ :int ], Proc.new { |i| }, { :convention => :stdcall })
231
+ * Function.new(:int, [ :int ], addr)
232
+ * Function.new(:int, [ :int ], addr, { :convention => :stdcall })
233
+ */
234
+ }
235
+
236
+ infoArgv[0] = rbReturnType;
237
+ infoArgv[1] = rbParamTypes;
238
+ infoArgv[2] = rbOptions;
239
+ rbFunctionInfo = rb_class_new_instance(rbOptions != Qnil ? 3 : 2, infoArgv, rbffi_FunctionTypeClass);
240
+
241
+ function_init(self, rbFunctionInfo, rbProc);
242
+
243
+ return self;
244
+ }
245
+
246
+ /*
247
+ * call-seq: initialize_copy(other)
248
+ * @return [nil]
249
+ * DO NOT CALL THIS METHOD
250
+ */
251
+ static VALUE
252
+ function_initialize_copy(VALUE self, VALUE other)
253
+ {
254
+ rb_raise(rb_eRuntimeError, "cannot duplicate function instances");
255
+ return Qnil;
256
+ }
257
+
258
+ VALUE
259
+ rbffi_Function_NewInstance(VALUE rbFunctionInfo, VALUE rbProc)
260
+ {
261
+ return function_init(function_allocate(rbffi_FunctionClass), rbFunctionInfo, rbProc);
262
+ }
263
+
264
+ VALUE
265
+ rbffi_Function_ForProc(VALUE rbFunctionInfo, VALUE proc)
266
+ {
267
+ VALUE callback, cbref, cbTable;
268
+ Function* fp;
269
+
270
+ cbref = RTEST(rb_ivar_defined(proc, id_cb_ref)) ? rb_ivar_get(proc, id_cb_ref) : Qnil;
271
+ /* If the first callback reference has the same function function signature, use it */
272
+ if (cbref != Qnil && CLASS_OF(cbref) == rbffi_FunctionClass) {
273
+ Data_Get_Struct(cbref, Function, fp);
274
+ if (fp->rbFunctionInfo == rbFunctionInfo) {
275
+ return cbref;
276
+ }
277
+ }
278
+
279
+ cbTable = RTEST(rb_ivar_defined(proc, id_cbtable)) ? rb_ivar_get(proc, id_cbtable) : Qnil;
280
+ if (cbTable != Qnil && (callback = rb_hash_aref(cbTable, rbFunctionInfo)) != Qnil) {
281
+ return callback;
282
+ }
283
+
284
+ /* No existing function for the proc with that signature, create a new one and cache it */
285
+ callback = rbffi_Function_NewInstance(rbFunctionInfo, proc);
286
+ if (cbref == Qnil) {
287
+ /* If there is no other cb already cached for this proc, we can use the ivar slot */
288
+ rb_ivar_set(proc, id_cb_ref, callback);
289
+ } else {
290
+ /* The proc instance has been used as more than one type of callback, store extras in a hash */
291
+ cbTable = rb_hash_new();
292
+ rb_ivar_set(proc, id_cbtable, cbTable);
293
+ rb_hash_aset(cbTable, rbFunctionInfo, callback);
294
+ }
295
+
296
+ return callback;
297
+ }
298
+
299
+ static VALUE
300
+ function_init(VALUE self, VALUE rbFunctionInfo, VALUE rbProc)
301
+ {
302
+ Function* fn = NULL;
303
+
304
+ Data_Get_Struct(self, Function, fn);
305
+
306
+ fn->rbFunctionInfo = rbFunctionInfo;
307
+
308
+ Data_Get_Struct(fn->rbFunctionInfo, FunctionType, fn->info);
309
+
310
+ if (rb_obj_is_kind_of(rbProc, rbffi_PointerClass)) {
311
+ Pointer* orig;
312
+ Data_Get_Struct(rbProc, Pointer, orig);
313
+ fn->base.memory = orig->memory;
314
+ fn->base.rbParent = rbProc;
315
+
316
+ } else if (rb_obj_is_kind_of(rbProc, rb_cProc) || rb_respond_to(rbProc, id_call)) {
317
+ if (fn->info->closurePool == NULL) {
318
+ fn->info->closurePool = rbffi_ClosurePool_New(sizeof(ffi_closure), callback_prep, fn->info);
319
+ if (fn->info->closurePool == NULL) {
320
+ rb_raise(rb_eNoMemError, "failed to create closure pool");
321
+ }
322
+ }
323
+
324
+ #if defined(DEFER_ASYNC_CALLBACK)
325
+ if (async_cb_thread == Qnil) {
326
+ #if !(defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)) && defined(_WIN32)
327
+ _pipe(async_cb_pipe, 1024, O_BINARY);
328
+ #elif !(defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL))
329
+ pipe(async_cb_pipe);
330
+ fcntl(async_cb_pipe[0], F_SETFL, fcntl(async_cb_pipe[0], F_GETFL) | O_NONBLOCK);
331
+ fcntl(async_cb_pipe[1], F_SETFL, fcntl(async_cb_pipe[1], F_GETFL) | O_NONBLOCK);
332
+ #endif
333
+ async_cb_thread = rb_thread_create(async_cb_event, NULL);
334
+ }
335
+
336
+ #endif
337
+
338
+ fn->closure = rbffi_Closure_Alloc(fn->info->closurePool);
339
+ fn->closure->info = fn;
340
+ fn->base.memory.address = fn->closure->code;
341
+ fn->base.memory.size = sizeof(*fn->closure);
342
+ fn->autorelease = true;
343
+
344
+ } else {
345
+ rb_raise(rb_eTypeError, "wrong argument type %s, expected pointer or proc",
346
+ rb_obj_classname(rbProc));
347
+ }
348
+
349
+ fn->rbProc = rbProc;
350
+
351
+ return self;
352
+ }
353
+
354
+ /*
355
+ * call-seq: call(*args)
356
+ * @param [Array] args function arguments
357
+ * @return [FFI::Type]
358
+ * Call the function
359
+ */
360
+ static VALUE
361
+ function_call(int argc, VALUE* argv, VALUE self)
362
+ {
363
+ Function* fn;
364
+
365
+ Data_Get_Struct(self, Function, fn);
366
+
367
+ return (*fn->info->invoke)(argc, argv, fn->base.memory.address, fn->info);
368
+ }
369
+
370
+ /*
371
+ * call-seq: attach(m, name)
372
+ * @param [Module] m
373
+ * @param [String] name
374
+ * @return [self]
375
+ * Attach a Function to the Module +m+ as +name+.
376
+ */
377
+ static VALUE
378
+ function_attach(VALUE self, VALUE module, VALUE name)
379
+ {
380
+ Function* fn;
381
+ char var[1024];
382
+
383
+ Data_Get_Struct(self, Function, fn);
384
+
385
+ if (fn->info->parameterCount == -1) {
386
+ rb_raise(rb_eRuntimeError, "cannot attach variadic functions");
387
+ return Qnil;
388
+ }
389
+
390
+ if (!rb_obj_is_kind_of(module, rb_cModule)) {
391
+ rb_raise(rb_eRuntimeError, "trying to attach function to non-module");
392
+ return Qnil;
393
+ }
394
+
395
+ if (fn->methodHandle == NULL) {
396
+ fn->methodHandle = rbffi_MethodHandle_Alloc(fn->info, fn->base.memory.address);
397
+ }
398
+
399
+ /*
400
+ * Stash the Function in a module variable so it does not get garbage collected
401
+ */
402
+ snprintf(var, sizeof(var), "@@%s", StringValueCStr(name));
403
+ rb_cv_set(module, var, self);
404
+
405
+ rb_define_singleton_method(module, StringValueCStr(name),
406
+ rbffi_MethodHandle_CodeAddress(fn->methodHandle), -1);
407
+
408
+
409
+ rb_define_method(module, StringValueCStr(name),
410
+ rbffi_MethodHandle_CodeAddress(fn->methodHandle), -1);
411
+
412
+ return self;
413
+ }
414
+
415
+ /*
416
+ * call-seq: autorelease = autorelease
417
+ * @param [Boolean] autorelease
418
+ * @return [self]
419
+ * Set +autorelease+ attribute (See {Pointer}).
420
+ */
421
+ static VALUE
422
+ function_set_autorelease(VALUE self, VALUE autorelease)
423
+ {
424
+ Function* fn;
425
+
426
+ Data_Get_Struct(self, Function, fn);
427
+
428
+ fn->autorelease = RTEST(autorelease);
429
+
430
+ return self;
431
+ }
432
+
433
+ static VALUE
434
+ function_autorelease_p(VALUE self)
435
+ {
436
+ Function* fn;
437
+
438
+ Data_Get_Struct(self, Function, fn);
439
+
440
+ return fn->autorelease ? Qtrue : Qfalse;
441
+ }
442
+
443
+ /*
444
+ * call-seq: free
445
+ * @return [self]
446
+ * Free memory allocated by Function.
447
+ */
448
+ static VALUE
449
+ function_release(VALUE self)
450
+ {
451
+ Function* fn;
452
+
453
+ Data_Get_Struct(self, Function, fn);
454
+
455
+ if (fn->closure == NULL) {
456
+ rb_raise(rb_eRuntimeError, "cannot free function which was not allocated");
457
+ }
458
+
459
+ rbffi_Closure_Free(fn->closure);
460
+ fn->closure = NULL;
461
+
462
+ return self;
463
+ }
464
+
465
+ static void
466
+ callback_invoke(ffi_cif* cif, void* retval, void** parameters, void* user_data)
467
+ {
468
+ struct gvl_callback cb = { 0 };
469
+
470
+ cb.closure = (Closure *) user_data;
471
+ cb.retval = retval;
472
+ cb.parameters = parameters;
473
+ cb.done = false;
474
+ cb.frame = rbffi_frame_current();
475
+
476
+ if (cb.frame != NULL) cb.frame->exc = Qnil;
477
+ if (cb.frame != NULL && cb.frame->has_gvl) {
478
+ callback_with_gvl(&cb);
479
+
480
+ #if defined(HAVE_RB_THREAD_CALL_WITH_GVL)
481
+ } else if (cb.frame != NULL) {
482
+ rb_thread_call_with_gvl(callback_with_gvl, &cb);
483
+ #endif
484
+ #if defined(DEFER_ASYNC_CALLBACK) && !defined(_WIN32)
485
+ } else {
486
+ bool empty = false;
487
+
488
+ pthread_mutex_init(&cb.async_mutex, NULL);
489
+ pthread_cond_init(&cb.async_cond, NULL);
490
+
491
+ /* Now signal the async callback thread */
492
+ pthread_mutex_lock(&async_cb_mutex);
493
+ empty = async_cb_list == NULL;
494
+ cb.next = async_cb_list;
495
+ async_cb_list = &cb;
496
+
497
+ #if !(defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL))
498
+ pthread_mutex_unlock(&async_cb_mutex);
499
+ /* Only signal if the list was empty */
500
+ if (empty) {
501
+ char c;
502
+ write(async_cb_pipe[1], &c, 1);
503
+ }
504
+ #else
505
+ pthread_cond_signal(&async_cb_cond);
506
+ pthread_mutex_unlock(&async_cb_mutex);
507
+ #endif
508
+
509
+ /* Wait for the thread executing the ruby callback to signal it is done */
510
+ pthread_mutex_lock(&cb.async_mutex);
511
+ while (!cb.done) {
512
+ pthread_cond_wait(&cb.async_cond, &cb.async_mutex);
513
+ }
514
+ pthread_mutex_unlock(&cb.async_mutex);
515
+ pthread_cond_destroy(&cb.async_cond);
516
+ pthread_mutex_destroy(&cb.async_mutex);
517
+
518
+ #elif defined(DEFER_ASYNC_CALLBACK) && defined(_WIN32)
519
+ } else {
520
+ bool empty = false;
521
+
522
+ cb.async_event = CreateEvent(NULL, FALSE, FALSE, NULL);
523
+
524
+ /* Now signal the async callback thread */
525
+ EnterCriticalSection(&async_cb_lock);
526
+ empty = async_cb_list == NULL;
527
+ cb.next = async_cb_list;
528
+ async_cb_list = &cb;
529
+ LeaveCriticalSection(&async_cb_lock);
530
+
531
+ #if !(defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL))
532
+ /* Only signal if the list was empty */
533
+ if (empty) {
534
+ char c;
535
+ write(async_cb_pipe[1], &c, 1);
536
+ }
537
+ #else
538
+ SetEvent(async_cb_cond);
539
+ #endif
540
+
541
+ /* Wait for the thread executing the ruby callback to signal it is done */
542
+ WaitForSingleObject(cb.async_event, INFINITE);
543
+ CloseHandle(cb.async_event);
544
+ #endif
545
+ }
546
+ }
547
+
548
+ #if defined(DEFER_ASYNC_CALLBACK)
549
+ struct async_wait {
550
+ void* cb;
551
+ bool stop;
552
+ };
553
+
554
+ static void * async_cb_wait(void *);
555
+ static void async_cb_stop(void *);
556
+
557
+ #if defined(HAVE_RB_THREAD_BLOCKING_REGION) || defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
558
+ static VALUE
559
+ async_cb_event(void* unused)
560
+ {
561
+ struct async_wait w = { 0 };
562
+
563
+ w.stop = false;
564
+ while (!w.stop) {
565
+ #if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
566
+ rb_thread_call_without_gvl(async_cb_wait, &w, async_cb_stop, &w);
567
+ #else
568
+ rb_thread_blocking_region(async_cb_wait, &w, async_cb_stop, &w);
569
+ #endif
570
+ if (w.cb != NULL) {
571
+ /* Start up a new ruby thread to run the ruby callback */
572
+ rb_thread_create(async_cb_call, w.cb);
573
+ }
574
+ }
575
+
576
+ return Qnil;
577
+ }
578
+
579
+ #elif defined(_WIN32)
580
+ static VALUE
581
+ async_cb_event(void* unused)
582
+ {
583
+ while (true) {
584
+ struct gvl_callback* cb;
585
+ char buf[64];
586
+ fd_set rfds;
587
+
588
+ FD_ZERO(&rfds);
589
+ FD_SET(async_cb_pipe[0], &rfds);
590
+ rb_thread_select(async_cb_pipe[0] + 1, &rfds, NULL, NULL, NULL);
591
+ read(async_cb_pipe[0], buf, sizeof(buf));
592
+
593
+ EnterCriticalSection(&async_cb_lock);
594
+ cb = async_cb_list;
595
+ async_cb_list = NULL;
596
+ LeaveCriticalSection(&async_cb_lock);
597
+
598
+ while (cb != NULL) {
599
+ struct gvl_callback* next = cb->next;
600
+ /* Start up a new ruby thread to run the ruby callback */
601
+ rb_thread_create(async_cb_call, cb);
602
+ cb = next;
603
+ }
604
+ }
605
+
606
+ return Qnil;
607
+ }
608
+ #else
609
+ static VALUE
610
+ async_cb_event(void* unused)
611
+ {
612
+ while (true) {
613
+ struct gvl_callback* cb;
614
+ char buf[64];
615
+
616
+ if (read(async_cb_pipe[0], buf, sizeof(buf)) < 0) {
617
+ rb_thread_wait_fd(async_cb_pipe[0]);
618
+ while (read(async_cb_pipe[0], buf, sizeof (buf)) < 0) {
619
+ if (rb_io_wait_readable(async_cb_pipe[0]) != Qtrue) {
620
+ return Qfalse;
621
+ }
622
+ }
623
+ }
624
+
625
+ pthread_mutex_lock(&async_cb_mutex);
626
+ cb = async_cb_list;
627
+ async_cb_list = NULL;
628
+ pthread_mutex_unlock(&async_cb_mutex);
629
+
630
+ while (cb != NULL) {
631
+ struct gvl_callback* next = cb->next;
632
+ /* Start up a new ruby thread to run the ruby callback */
633
+ rb_thread_create(async_cb_call, cb);
634
+ cb = next;
635
+ }
636
+ }
637
+
638
+ return Qnil;
639
+ }
640
+ #endif
641
+
642
+ #ifdef _WIN32
643
+ static void *
644
+ async_cb_wait(void *data)
645
+ {
646
+ struct async_wait* w = (struct async_wait *) data;
647
+
648
+ w->cb = NULL;
649
+
650
+ EnterCriticalSection(&async_cb_lock);
651
+
652
+ while (!w->stop && async_cb_list == NULL) {
653
+ LeaveCriticalSection(&async_cb_lock);
654
+ WaitForSingleObject(async_cb_cond, INFINITE);
655
+ EnterCriticalSection(&async_cb_lock);
656
+ }
657
+
658
+ if (async_cb_list != NULL) {
659
+ w->cb = async_cb_list;
660
+ async_cb_list = async_cb_list->next;
661
+ }
662
+
663
+ LeaveCriticalSection(&async_cb_lock);
664
+
665
+ return NULL;
666
+ }
667
+
668
+ static void
669
+ async_cb_stop(void *data)
670
+ {
671
+ struct async_wait* w = (struct async_wait *) data;
672
+
673
+ EnterCriticalSection(&async_cb_lock);
674
+ w->stop = true;
675
+ LeaveCriticalSection(&async_cb_lock);
676
+ SetEvent(async_cb_cond);
677
+ }
678
+
679
+ #else
680
+ static void *
681
+ async_cb_wait(void *data)
682
+ {
683
+ struct async_wait* w = (struct async_wait *) data;
684
+
685
+ w->cb = NULL;
686
+
687
+ pthread_mutex_lock(&async_cb_mutex);
688
+
689
+ while (!w->stop && async_cb_list == NULL) {
690
+ pthread_cond_wait(&async_cb_cond, &async_cb_mutex);
691
+ }
692
+
693
+ if (async_cb_list != NULL) {
694
+ w->cb = async_cb_list;
695
+ async_cb_list = async_cb_list->next;
696
+ }
697
+
698
+ pthread_mutex_unlock(&async_cb_mutex);
699
+
700
+ return NULL;
701
+ }
702
+
703
+ static void
704
+ async_cb_stop(void *data)
705
+ {
706
+ struct async_wait* w = (struct async_wait *) data;
707
+
708
+ pthread_mutex_lock(&async_cb_mutex);
709
+ w->stop = true;
710
+ pthread_cond_signal(&async_cb_cond);
711
+ pthread_mutex_unlock(&async_cb_mutex);
712
+ }
713
+ #endif
714
+
715
+ static VALUE
716
+ async_cb_call(void *data)
717
+ {
718
+ struct gvl_callback* cb = (struct gvl_callback *) data;
719
+
720
+ callback_with_gvl(data);
721
+
722
+ /* Signal the original native thread that the ruby code has completed */
723
+ #ifdef _WIN32
724
+ SetEvent(cb->async_event);
725
+ #else
726
+ pthread_mutex_lock(&cb->async_mutex);
727
+ cb->done = true;
728
+ pthread_cond_signal(&cb->async_cond);
729
+ pthread_mutex_unlock(&cb->async_mutex);
730
+ #endif
731
+
732
+ return Qnil;
733
+ }
734
+
735
+ #endif
736
+
737
+ static void *
738
+ callback_with_gvl(void* data)
739
+ {
740
+ rb_rescue2(invoke_callback, (VALUE) data, save_callback_exception, (VALUE) data, rb_eException, (VALUE) 0);
741
+ return NULL;
742
+ }
743
+
744
+ static VALUE
745
+ invoke_callback(void* data)
746
+ {
747
+ struct gvl_callback* cb = (struct gvl_callback *) data;
748
+
749
+ Function* fn = (Function *) cb->closure->info;
750
+ FunctionType *cbInfo = fn->info;
751
+ Type* returnType = cbInfo->returnType;
752
+ void* retval = cb->retval;
753
+ void** parameters = cb->parameters;
754
+ VALUE* rbParams;
755
+ VALUE rbReturnType = cbInfo->rbReturnType;
756
+ VALUE rbReturnValue;
757
+ int i;
758
+
759
+ rbParams = ALLOCA_N(VALUE, cbInfo->parameterCount);
760
+ for (i = 0; i < cbInfo->parameterCount; ++i) {
761
+ VALUE param;
762
+ Type* paramType = cbInfo->parameterTypes[i];
763
+ VALUE rbParamType = rb_ary_entry(cbInfo->rbParameterTypes, i);
764
+
765
+ if (unlikely(paramType->nativeType == NATIVE_MAPPED)) {
766
+ rbParamType = ((MappedType *) paramType)->rbType;
767
+ paramType = ((MappedType *) paramType)->type;
768
+ }
769
+
770
+ switch (paramType->nativeType) {
771
+ case NATIVE_INT8:
772
+ param = INT2NUM(*(int8_t *) parameters[i]);
773
+ break;
774
+ case NATIVE_UINT8:
775
+ param = UINT2NUM(*(uint8_t *) parameters[i]);
776
+ break;
777
+ case NATIVE_INT16:
778
+ param = INT2NUM(*(int16_t *) parameters[i]);
779
+ break;
780
+ case NATIVE_UINT16:
781
+ param = UINT2NUM(*(uint16_t *) parameters[i]);
782
+ break;
783
+ case NATIVE_INT32:
784
+ param = INT2NUM(*(int32_t *) parameters[i]);
785
+ break;
786
+ case NATIVE_UINT32:
787
+ param = UINT2NUM(*(uint32_t *) parameters[i]);
788
+ break;
789
+ case NATIVE_INT64:
790
+ param = LL2NUM(*(int64_t *) parameters[i]);
791
+ break;
792
+ case NATIVE_UINT64:
793
+ param = ULL2NUM(*(uint64_t *) parameters[i]);
794
+ break;
795
+ case NATIVE_LONG:
796
+ param = LONG2NUM(*(long *) parameters[i]);
797
+ break;
798
+ case NATIVE_ULONG:
799
+ param = ULONG2NUM(*(unsigned long *) parameters[i]);
800
+ break;
801
+ case NATIVE_FLOAT32:
802
+ param = rb_float_new(*(float *) parameters[i]);
803
+ break;
804
+ case NATIVE_FLOAT64:
805
+ param = rb_float_new(*(double *) parameters[i]);
806
+ break;
807
+ case NATIVE_LONGDOUBLE:
808
+ param = rbffi_longdouble_new(*(long double *) parameters[i]);
809
+ break;
810
+ case NATIVE_STRING:
811
+ param = (*(void **) parameters[i] != NULL) ? rb_tainted_str_new2(*(char **) parameters[i]) : Qnil;
812
+ break;
813
+ case NATIVE_POINTER:
814
+ param = rbffi_Pointer_NewInstance(*(void **) parameters[i]);
815
+ break;
816
+ case NATIVE_BOOL:
817
+ param = (*(uint8_t *) parameters[i]) ? Qtrue : Qfalse;
818
+ break;
819
+
820
+ case NATIVE_FUNCTION:
821
+ case NATIVE_CALLBACK:
822
+ case NATIVE_STRUCT:
823
+ param = rbffi_NativeValue_ToRuby(paramType, rbParamType, parameters[i]);
824
+ break;
825
+
826
+ default:
827
+ param = Qnil;
828
+ break;
829
+ }
830
+
831
+ /* Convert the native value into a custom ruby value */
832
+ if (unlikely(cbInfo->parameterTypes[i]->nativeType == NATIVE_MAPPED)) {
833
+ VALUE values[] = { param, Qnil };
834
+ param = rb_funcall2(((MappedType *) cbInfo->parameterTypes[i])->rbConverter, id_from_native, 2, values);
835
+ }
836
+
837
+ rbParams[i] = param;
838
+ }
839
+
840
+ rbReturnValue = rb_funcall2(fn->rbProc, id_call, cbInfo->parameterCount, rbParams);
841
+
842
+ if (unlikely(returnType->nativeType == NATIVE_MAPPED)) {
843
+ VALUE values[] = { rbReturnValue, Qnil };
844
+ rbReturnValue = rb_funcall2(((MappedType *) returnType)->rbConverter, id_to_native, 2, values);
845
+ rbReturnType = ((MappedType *) returnType)->rbType;
846
+ returnType = ((MappedType* ) returnType)->type;
847
+ }
848
+
849
+ if (rbReturnValue == Qnil || TYPE(rbReturnValue) == T_NIL) {
850
+ memset(retval, 0, returnType->ffiType->size);
851
+ } else switch (returnType->nativeType) {
852
+ case NATIVE_INT8:
853
+ case NATIVE_INT16:
854
+ case NATIVE_INT32:
855
+ *((ffi_sarg *) retval) = NUM2INT(rbReturnValue);
856
+ break;
857
+ case NATIVE_UINT8:
858
+ case NATIVE_UINT16:
859
+ case NATIVE_UINT32:
860
+ *((ffi_arg *) retval) = NUM2UINT(rbReturnValue);
861
+ break;
862
+ case NATIVE_INT64:
863
+ *((int64_t *) retval) = NUM2LL(rbReturnValue);
864
+ break;
865
+ case NATIVE_UINT64:
866
+ *((uint64_t *) retval) = NUM2ULL(rbReturnValue);
867
+ break;
868
+ case NATIVE_LONG:
869
+ *((ffi_sarg *) retval) = NUM2LONG(rbReturnValue);
870
+ break;
871
+ case NATIVE_ULONG:
872
+ *((ffi_arg *) retval) = NUM2ULONG(rbReturnValue);
873
+ break;
874
+ case NATIVE_FLOAT32:
875
+ *((float *) retval) = (float) NUM2DBL(rbReturnValue);
876
+ break;
877
+ case NATIVE_FLOAT64:
878
+ *((double *) retval) = NUM2DBL(rbReturnValue);
879
+ break;
880
+ case NATIVE_POINTER:
881
+ if (TYPE(rbReturnValue) == T_DATA && rb_obj_is_kind_of(rbReturnValue, rbffi_PointerClass)) {
882
+ *((void **) retval) = ((AbstractMemory *) DATA_PTR(rbReturnValue))->address;
883
+ } else {
884
+ /* Default to returning NULL if not a value pointer object. handles nil case as well */
885
+ *((void **) retval) = NULL;
886
+ }
887
+ break;
888
+
889
+ case NATIVE_BOOL:
890
+ *((ffi_arg *) retval) = rbReturnValue == Qtrue;
891
+ break;
892
+
893
+ case NATIVE_FUNCTION:
894
+ case NATIVE_CALLBACK:
895
+ if (TYPE(rbReturnValue) == T_DATA && rb_obj_is_kind_of(rbReturnValue, rbffi_PointerClass)) {
896
+
897
+ *((void **) retval) = ((AbstractMemory *) DATA_PTR(rbReturnValue))->address;
898
+
899
+ } else if (rb_obj_is_kind_of(rbReturnValue, rb_cProc) || rb_respond_to(rbReturnValue, id_call)) {
900
+ VALUE function;
901
+
902
+ function = rbffi_Function_ForProc(rbReturnType, rbReturnValue);
903
+
904
+ *((void **) retval) = ((AbstractMemory *) DATA_PTR(function))->address;
905
+ } else {
906
+ *((void **) retval) = NULL;
907
+ }
908
+ break;
909
+
910
+ case NATIVE_STRUCT:
911
+ if (TYPE(rbReturnValue) == T_DATA && rb_obj_is_kind_of(rbReturnValue, rbffi_StructClass)) {
912
+ AbstractMemory* memory = ((Struct *) DATA_PTR(rbReturnValue))->pointer;
913
+
914
+ if (memory->address != NULL) {
915
+ memcpy(retval, memory->address, returnType->ffiType->size);
916
+
917
+ } else {
918
+ memset(retval, 0, returnType->ffiType->size);
919
+ }
920
+
921
+ } else {
922
+ memset(retval, 0, returnType->ffiType->size);
923
+ }
924
+ break;
925
+
926
+ default:
927
+ *((ffi_arg *) retval) = 0;
928
+ break;
929
+ }
930
+
931
+ return Qnil;
932
+ }
933
+
934
+ static VALUE
935
+ save_callback_exception(void* data, VALUE exc)
936
+ {
937
+ struct gvl_callback* cb = (struct gvl_callback *) data;
938
+
939
+ memset(cb->retval, 0, ((Function *) cb->closure->info)->info->returnType->ffiType->size);
940
+ if (cb->frame != NULL) cb->frame->exc = exc;
941
+
942
+ return Qnil;
943
+ }
944
+
945
+ static bool
946
+ callback_prep(void* ctx, void* code, Closure* closure, char* errmsg, size_t errmsgsize)
947
+ {
948
+ FunctionType* fnInfo = (FunctionType *) ctx;
949
+ ffi_status ffiStatus;
950
+
951
+ ffiStatus = ffi_prep_closure(code, &fnInfo->ffi_cif, callback_invoke, closure);
952
+ if (ffiStatus != FFI_OK) {
953
+ snprintf(errmsg, errmsgsize, "ffi_prep_closure failed. status=%#x", ffiStatus);
954
+ return false;
955
+ }
956
+
957
+ return true;
958
+ }
959
+
960
+ void
961
+ rbffi_Function_Init(VALUE moduleFFI)
962
+ {
963
+ rbffi_FunctionInfo_Init(moduleFFI);
964
+ /*
965
+ * Document-class: FFI::Function < FFI::Pointer
966
+ */
967
+ rbffi_FunctionClass = rb_define_class_under(moduleFFI, "Function", rbffi_PointerClass);
968
+
969
+ rb_global_variable(&rbffi_FunctionClass);
970
+ rb_define_alloc_func(rbffi_FunctionClass, function_allocate);
971
+
972
+ rb_define_method(rbffi_FunctionClass, "initialize", function_initialize, -1);
973
+ rb_define_method(rbffi_FunctionClass, "initialize_copy", function_initialize_copy, 1);
974
+ rb_define_method(rbffi_FunctionClass, "call", function_call, -1);
975
+ rb_define_method(rbffi_FunctionClass, "attach", function_attach, 2);
976
+ rb_define_method(rbffi_FunctionClass, "free", function_release, 0);
977
+ rb_define_method(rbffi_FunctionClass, "autorelease=", function_set_autorelease, 1);
978
+ /*
979
+ * call-seq: autorelease
980
+ * @return [Boolean]
981
+ * Get +autorelease+ attribute.
982
+ * Synonymous for {#autorelease?}.
983
+ */
984
+ rb_define_method(rbffi_FunctionClass, "autorelease", function_autorelease_p, 0);
985
+ /*
986
+ * call-seq: autorelease?
987
+ * @return [Boolean] +autorelease+ attribute
988
+ * Get +autorelease+ attribute.
989
+ */
990
+ rb_define_method(rbffi_FunctionClass, "autorelease?", function_autorelease_p, 0);
991
+
992
+ id_call = rb_intern("call");
993
+ id_cbtable = rb_intern("@__ffi_callback_table__");
994
+ id_cb_ref = rb_intern("@__ffi_callback__");
995
+ id_to_native = rb_intern("to_native");
996
+ id_from_native = rb_intern("from_native");
997
+ #if defined(_WIN32)
998
+ InitializeCriticalSection(&async_cb_lock);
999
+ async_cb_cond = CreateEvent(NULL, FALSE, FALSE, NULL);
1000
+ #endif
1001
+ }